blob: 7943a9e4c3fc3f678770651effb22546487aef9a [file] [log] [blame]
/*
* 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;
}
}