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