| /* |
| * 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.ContentValues; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.SharedPreferences; |
| import android.content.res.Resources; |
| import android.database.Cursor; |
| import android.net.Uri; |
| import android.os.PowerManager; |
| import android.preference.PreferenceManager; |
| 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"; |
| |
| 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. |
| */ |
| // TODO Grab a wake lock here? |
| Intent serviceIntent = new Intent(context, DismissAllAlarmsService.class); |
| context.startService(serviceIntent); |
| } 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); |
| } |
| } |
| |
| /** |
| * 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; |
| } |
| |
| // Check the settings to see if alerts are disabled |
| SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); |
| String reminderType = prefs.getString(CalendarPreferenceActivity.KEY_ALERTS_TYPE, |
| CalendarPreferenceActivity.ALERT_TYPE_STATUS_BAR); |
| if (reminderType.equals(CalendarPreferenceActivity.ALERT_TYPE_OFF)) { |
| 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; |
| } |
| } |
| |