AlertActivity.java revision 23e7da3eacee7bceb105cdfc7b5329c7a43846d5
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 17package com.android.calendar.alerts; 18 19import com.android.calendar.AsyncQueryService; 20import com.android.calendar.CalendarController; 21import com.android.calendar.CalendarController.EventType; 22import com.android.calendar.R; 23import com.android.calendar.R.id; 24import com.android.calendar.R.layout; 25import com.android.calendar.R.string; 26import com.android.calendar.Utils; 27 28import android.app.Activity; 29import android.app.AlarmManager; 30import android.app.NotificationManager; 31import android.content.ContentResolver; 32import android.content.ContentValues; 33import android.content.Context; 34import android.database.Cursor; 35import android.net.Uri; 36import android.os.Bundle; 37import android.provider.Calendar.CalendarAlerts; 38import android.provider.Calendar.CalendarAlertsColumns; 39import android.view.View; 40import android.view.ViewGroup; 41import android.view.WindowManager; 42import android.view.View.OnClickListener; 43import android.widget.AdapterView; 44import android.widget.Button; 45import android.widget.ListView; 46import android.widget.AdapterView.OnItemClickListener; 47 48/** 49 * The alert panel that pops up when there is a calendar event alarm. 50 * This activity is started by an intent that specifies an event id. 51 */ 52public class AlertActivity extends Activity { 53 54 // The default snooze delay: 5 minutes 55 public static final long SNOOZE_DELAY = 5 * 60 * 1000L; 56 57 private static final String[] PROJECTION = new String[] { 58 CalendarAlerts._ID, // 0 59 CalendarAlerts.TITLE, // 1 60 CalendarAlerts.EVENT_LOCATION, // 2 61 CalendarAlerts.ALL_DAY, // 3 62 CalendarAlerts.BEGIN, // 4 63 CalendarAlerts.END, // 5 64 CalendarAlerts.EVENT_ID, // 6 65 CalendarAlerts.COLOR, // 7 66 CalendarAlerts.RRULE, // 8 67 CalendarAlerts.HAS_ALARM, // 9 68 CalendarAlerts.STATE, // 10 69 CalendarAlerts.ALARM_TIME, // 11 70 }; 71 72 public static final int INDEX_ROW_ID = 0; 73 public static final int INDEX_TITLE = 1; 74 public static final int INDEX_EVENT_LOCATION = 2; 75 public static final int INDEX_ALL_DAY = 3; 76 public static final int INDEX_BEGIN = 4; 77 public static final int INDEX_END = 5; 78 public static final int INDEX_EVENT_ID = 6; 79 public static final int INDEX_COLOR = 7; 80 public static final int INDEX_RRULE = 8; 81 public static final int INDEX_HAS_ALARM = 9; 82 public static final int INDEX_STATE = 10; 83 public static final int INDEX_ALARM_TIME = 11; 84 85 private static final String SELECTION = CalendarAlerts.STATE + "=?"; 86 private static final String[] SELECTIONARG = new String[] { 87 Integer.toString(CalendarAlerts.FIRED) 88 }; 89 90 // We use one notification id for all events so that we don't clutter 91 // the notification screen. It doesn't matter what the id is, as long 92 // as it is used consistently everywhere. 93 public static final int NOTIFICATION_ID = 0; 94 95 private ContentResolver mResolver; 96 private AlertAdapter mAdapter; 97 private QueryHandler mQueryHandler; 98 private Cursor mCursor; 99 private ListView mListView; 100 private Button mSnoozeAllButton; 101 private Button mDismissAllButton; 102 103 104 private void dismissFiredAlarms() { 105 ContentValues values = new ContentValues(1 /* size */); 106 values.put(PROJECTION[INDEX_STATE], CalendarAlerts.DISMISSED); 107 String selection = CalendarAlerts.STATE + "=" + CalendarAlerts.FIRED; 108 mQueryHandler.startUpdate(0, null, CalendarAlerts.CONTENT_URI, values, 109 selection, null /* selectionArgs */, Utils.UNDO_DELAY); 110 } 111 112 private void dismissAlarm(long id) { 113 ContentValues values = new ContentValues(1 /* size */); 114 values.put(PROJECTION[INDEX_STATE], CalendarAlerts.DISMISSED); 115 String selection = CalendarAlerts._ID + "=" + id; 116 mQueryHandler.startUpdate(0, null, CalendarAlerts.CONTENT_URI, values, 117 selection, null /* selectionArgs */, Utils.UNDO_DELAY); 118 } 119 120 private class QueryHandler extends AsyncQueryService { 121 public QueryHandler(Context context) { 122 super(context); 123 } 124 125 @Override 126 protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 127 // Only set mCursor if the Activity is not finishing. Otherwise close the cursor. 128 if (!isFinishing()) { 129 mCursor = cursor; 130 mAdapter.changeCursor(cursor); 131 132 // The results are in, enable the buttons 133 mSnoozeAllButton.setEnabled(true); 134 mDismissAllButton.setEnabled(true); 135 } else { 136 cursor.close(); 137 } 138 } 139 140 @Override 141 protected void onInsertComplete(int token, Object cookie, Uri uri) { 142 if (uri != null) { 143 Long alarmTime = (Long) cookie; 144 145 if (alarmTime != 0) { 146 // Set a new alarm to go off after the snooze delay. 147 AlarmManager alarmManager = 148 (AlarmManager) getSystemService(Context.ALARM_SERVICE); 149 CalendarAlerts.scheduleAlarm(AlertActivity.this, alarmManager, alarmTime); 150 } 151 } 152 } 153 154 @Override 155 protected void onUpdateComplete(int token, Object cookie, int result) { 156 // Ignore 157 } 158 } 159 160 private static ContentValues makeContentValues(long eventId, long begin, long end, 161 long alarmTime, int minutes) { 162 ContentValues values = new ContentValues(); 163 values.put(CalendarAlerts.EVENT_ID, eventId); 164 values.put(CalendarAlerts.BEGIN, begin); 165 values.put(CalendarAlerts.END, end); 166 values.put(CalendarAlerts.ALARM_TIME, alarmTime); 167 long currentTime = System.currentTimeMillis(); 168 values.put(CalendarAlerts.CREATION_TIME, currentTime); 169 values.put(CalendarAlerts.RECEIVED_TIME, 0); 170 values.put(CalendarAlerts.NOTIFY_TIME, 0); 171 values.put(CalendarAlerts.STATE, CalendarAlertsColumns.SCHEDULED); 172 values.put(CalendarAlerts.MINUTES, minutes); 173 return values; 174 } 175 176 private OnItemClickListener mViewListener = new OnItemClickListener() { 177 178 public void onItemClick(AdapterView<?> parent, View view, int position, 179 long i) { 180 AlertActivity alertActivity = AlertActivity.this; 181 Cursor cursor = alertActivity.getItemForView(view); 182 183 // Mark this alarm as DISMISSED 184 dismissAlarm(cursor.getLong(INDEX_ROW_ID)); 185 186 long id = cursor.getInt(AlertActivity.INDEX_EVENT_ID); 187 long startMillis = cursor.getLong(AlertActivity.INDEX_BEGIN); 188 long endMillis = cursor.getLong(AlertActivity.INDEX_END); 189 CalendarController.getInstance(alertActivity).sendEventRelatedEvent(alertActivity, 190 EventType.VIEW_EVENT, id, startMillis, endMillis, 0, 0); 191 192 alertActivity.finish(); 193 } 194 }; 195 196 @Override 197 protected void onCreate(Bundle icicle) { 198 super.onCreate(icicle); 199 200 setContentView(R.layout.alert_activity); 201 setTitle(R.string.alert_title); 202 203 WindowManager.LayoutParams lp = getWindow().getAttributes(); 204 lp.width = ViewGroup.LayoutParams.MATCH_PARENT; 205 lp.height = ViewGroup.LayoutParams.MATCH_PARENT; 206 207 getWindow().setAttributes(lp); 208 209 mResolver = getContentResolver(); 210 mQueryHandler = new QueryHandler(this); 211 mAdapter = new AlertAdapter(this, R.layout.alert_item); 212 213 mListView = (ListView) findViewById(R.id.alert_container); 214 mListView.setItemsCanFocus(true); 215 mListView.setAdapter(mAdapter); 216 mListView.setOnItemClickListener(mViewListener); 217 218 mSnoozeAllButton = (Button) findViewById(R.id.snooze_all); 219 mSnoozeAllButton.setOnClickListener(mSnoozeAllListener); 220 mDismissAllButton = (Button) findViewById(R.id.dismiss_all); 221 mDismissAllButton.setOnClickListener(mDismissAllListener); 222 223 // Disable the buttons, since they need mCursor, which is created asynchronously 224 mSnoozeAllButton.setEnabled(false); 225 mDismissAllButton.setEnabled(false); 226 } 227 228 @Override 229 protected void onResume() { 230 super.onResume(); 231 232 // If the cursor is null, start the async handler. If it is not null just requery. 233 if (mCursor == null) { 234 Uri uri = CalendarAlerts.CONTENT_URI_BY_INSTANCE; 235 mQueryHandler.startQuery(0, null, uri, PROJECTION, SELECTION, 236 SELECTIONARG, CalendarAlerts.DEFAULT_SORT_ORDER); 237 } else { 238 mCursor.requery(); 239 } 240 } 241 242 @Override 243 protected void onStop() { 244 super.onStop(); 245 AlertService.updateAlertNotification(this); 246 247 if (mCursor != null) { 248 mCursor.deactivate(); 249 } 250 } 251 252 @Override 253 protected void onDestroy() { 254 super.onDestroy(); 255 if (mCursor != null) { 256 mCursor.close(); 257 } 258 } 259 260 private OnClickListener mSnoozeAllListener = new OnClickListener() { 261 public void onClick(View v) { 262 long alarmTime = System.currentTimeMillis() + SNOOZE_DELAY; 263 264 NotificationManager nm = 265 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 266 nm.cancel(NOTIFICATION_ID); 267 268 long scheduleAlarmTime = 0; 269 mCursor.moveToPosition(-1); 270 while (mCursor.moveToNext()) { 271 long eventId = mCursor.getLong(INDEX_EVENT_ID); 272 long begin = mCursor.getLong(INDEX_BEGIN); 273 long end = mCursor.getLong(INDEX_END); 274 275 // Set the "minutes" to zero to indicate this is a snoozed 276 // alarm. There is code in AlertService.java that checks 277 // this field. 278 ContentValues values = 279 makeContentValues(eventId, begin, end, alarmTime, 0 /* minutes */); 280 281 // Create a new alarm entry in the CalendarAlerts table 282 if (mCursor.isLast()) { 283 scheduleAlarmTime = alarmTime; 284 } 285 mQueryHandler.startInsert(0, scheduleAlarmTime, CalendarAlerts.CONTENT_URI, values, 286 Utils.UNDO_DELAY); 287 } 288 289 dismissFiredAlarms(); 290 291 finish(); 292 } 293 }; 294 295 private OnClickListener mDismissAllListener = new OnClickListener() { 296 public void onClick(View v) { 297 NotificationManager nm = 298 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 299 nm.cancel(NOTIFICATION_ID); 300 301 dismissFiredAlarms(); 302 303 finish(); 304 } 305 }; 306 307 public boolean isEmpty() { 308 return (mCursor.getCount() == 0); 309 } 310 311 public Cursor getItemForView(View view) { 312 int index = mListView.getPositionForView(view); 313 if (index < 0) { 314 return null; 315 } 316 return (Cursor) mListView.getAdapter().getItem(index); 317 } 318} 319