summaryrefslogtreecommitdiffstats
path: root/src/com/android/calendar/AlertReceiver.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/calendar/AlertReceiver.java')
-rw-r--r--src/com/android/calendar/AlertReceiver.java215
1 files changed, 215 insertions, 0 deletions
diff --git a/src/com/android/calendar/AlertReceiver.java b/src/com/android/calendar/AlertReceiver.java
new file mode 100644
index 00000000..ea2d549f
--- /dev/null
+++ b/src/com/android/calendar/AlertReceiver.java
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.calendar;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.Service;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.PowerManager;
+import android.provider.Calendar.CalendarAlerts;
+
+/**
+ * Receives android.intent.action.EVENT_REMINDER intents and handles
+ * event reminders. The intent URI specifies an alert id in the
+ * CalendarAlerts database table. This class also receives the
+ * BOOT_COMPLETED intent so that it can add a status bar notification
+ * if there are Calendar event alarms that have not been dismissed.
+ * It also receives the TIME_CHANGED action so that it can fire off
+ * snoozed alarms that have become ready. The real work is done in
+ * the AlertService class.
+ */
+public class AlertReceiver extends BroadcastReceiver {
+
+ private static final String[] ALERT_PROJECTION = new String[] {
+ CalendarAlerts.TITLE, // 0
+ CalendarAlerts.EVENT_LOCATION, // 1
+ };
+ private static final int ALERT_INDEX_TITLE = 0;
+ private static final int ALERT_INDEX_EVENT_LOCATION = 1;
+
+ private static final String DELETE_ACTION = "delete";
+
+ private static final String[] PROJECTION = new String[] {
+ CalendarAlerts._ID, // 0
+ CalendarAlerts.STATE, // 1
+ };
+
+ public static final int INDEX_STATE = 1;
+
+ static final Object mStartingServiceSync = new Object();
+ static PowerManager.WakeLock mStartingService;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (DELETE_ACTION.equals(intent.getAction())) {
+
+ /* The user has clicked the "Clear All Notifications"
+ * buttons so dismiss all Calendar alerts.
+ */
+ dismissAllEvents(context);
+ } else {
+ Intent i = new Intent();
+ i.setClass(context, AlertService.class);
+ i.putExtras(intent);
+ i.putExtra("action", intent.getAction());
+ Uri uri = intent.getData();
+
+ // This intent might be a BOOT_COMPLETED so it might not have a Uri.
+ if (uri != null) {
+ i.putExtra("uri", uri.toString());
+ }
+ beginStartingService(context, i);
+ }
+ }
+
+ private void dismissAllEvents(Context context) {
+ Uri uri = CalendarAlerts.CONTENT_URI_BY_INSTANCE;
+ String selection = CalendarAlerts.STATE + "=" + CalendarAlerts.FIRED;
+ ContentResolver resolver = context.getContentResolver();
+ Cursor cursor = resolver.query(uri, PROJECTION, selection, null, null);
+ if (cursor != null) {
+ cursor.moveToPosition(-1);
+ while (cursor.moveToNext()) {
+ cursor.updateInt(INDEX_STATE, CalendarAlerts.DISMISSED);
+ }
+ cursor.commitUpdates();
+ cursor.close();
+ }
+ }
+
+ /**
+ * Start the service to process the current event notifications, acquiring
+ * the wake lock before returning to ensure that the service will run.
+ */
+ public static void beginStartingService(Context context, Intent intent) {
+ synchronized (mStartingServiceSync) {
+ if (mStartingService == null) {
+ PowerManager pm =
+ (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ "StartingAlertService");
+ mStartingService.setReferenceCounted(false);
+ }
+ mStartingService.acquire();
+ context.startService(intent);
+ }
+ }
+
+ /**
+ * Called back by the service when it has finished processing notifications,
+ * releasing the wake lock if the service is now stopping.
+ */
+ public static void finishStartingService(Service service, int startId) {
+ synchronized (mStartingServiceSync) {
+ if (mStartingService != null) {
+ if (service.stopSelfResult(startId)) {
+ mStartingService.release();
+ }
+ }
+ }
+ }
+
+ public static void updateAlertNotification(Context context) {
+ // This can be called regularly to synchronize the alert notification
+ // with the contents of the CalendarAlerts table.
+
+ ContentResolver cr = context.getContentResolver();
+
+ if (cr == null) {
+ return;
+ }
+
+ String selection = CalendarAlerts.STATE + "=" + CalendarAlerts.FIRED;
+ Cursor alertCursor = CalendarAlerts.query(cr, ALERT_PROJECTION, selection, null);
+
+ NotificationManager nm =
+ (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+
+ if (alertCursor == null) {
+ nm.cancel(AlertActivity.NOTIFICATION_ID);
+ return;
+ }
+
+ if (!alertCursor.moveToFirst()) {
+ alertCursor.close();
+ nm.cancel(AlertActivity.NOTIFICATION_ID);
+ return;
+ }
+
+ String title = alertCursor.getString(ALERT_INDEX_TITLE);
+ String location = alertCursor.getString(ALERT_INDEX_EVENT_LOCATION);
+
+ Notification notification = AlertReceiver.makeNewAlertNotification(context, title,
+ location, alertCursor.getCount());
+ alertCursor.close();
+
+ nm.notify(0, notification);
+ }
+
+ public static Notification makeNewAlertNotification(Context context, String title,
+ String location, int numReminders) {
+ Resources res = context.getResources();
+
+ // Create an intent triggered by clicking on the status icon.
+ Intent clickIntent = new Intent();
+ clickIntent.setClass(context, AlertActivity.class);
+ clickIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ // Create an intent triggered by clicking on the "Clear All Notifications" button
+ Intent deleteIntent = new Intent();
+ deleteIntent.setClass(context, AlertReceiver.class);
+ deleteIntent.setAction(DELETE_ACTION);
+
+ if (title == null || title.length() == 0) {
+ title = res.getString(R.string.no_title_label);
+ }
+
+ String helperString;
+ if (numReminders > 1) {
+ String format;
+ if (numReminders == 2) {
+ format = res.getString(R.string.alert_missed_events_single);
+ } else {
+ format = res.getString(R.string.alert_missed_events_multiple);
+ }
+ helperString = String.format(format, numReminders - 1);
+ } else {
+ helperString = location;
+ }
+
+ Notification notification = new Notification(
+ R.drawable.stat_notify_calendar,
+ null,
+ System.currentTimeMillis());
+ notification.setLatestEventInfo(context,
+ title,
+ helperString,
+ PendingIntent.getActivity(context, 0, clickIntent, 0));
+ notification.deleteIntent = PendingIntent.getBroadcast(context, 0, deleteIntent, 0);
+
+ return notification;
+ }
+}
+