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