AlertActivity.java revision 8f7f1abe54f206c490d2683f80646f514d98939b
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 android.app.Activity; 20import android.app.NotificationManager; 21import android.app.TaskStackBuilder; 22import android.content.ContentValues; 23import android.content.Context; 24import android.content.Intent; 25import android.database.Cursor; 26import android.net.Uri; 27import android.os.Bundle; 28import android.provider.CalendarContract; 29import android.provider.CalendarContract.CalendarAlerts; 30import android.util.Log; 31import android.view.View; 32import android.view.View.OnClickListener; 33import android.widget.AdapterView; 34import android.widget.AdapterView.OnItemClickListener; 35import android.widget.Button; 36import android.widget.ListView; 37 38import com.android.calendar.AsyncQueryService; 39import com.android.calendar.EventInfoActivity; 40import com.android.calendar.R; 41import com.android.calendar.Utils; 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 + "=? AND " + 79 CalendarAlerts.END + "<?"; 80 81 private AlertAdapter mAdapter; 82 private QueryHandler mQueryHandler; 83 private Cursor mCursor; 84 private ListView mListView; 85 private Button mDismissAllButton; 86 87 88 private void dismissFiredAlarmsForPastEvents() { 89 ContentValues values = new ContentValues(1 /* size */); 90 values.put(PROJECTION[INDEX_STATE], CalendarAlerts.STATE_DISMISSED); 91 String selection = CalendarAlerts.STATE + "=" + CalendarAlerts.STATE_FIRED + " AND " + 92 CalendarAlerts.END + "<" + Long.toString(System.currentTimeMillis()); 93 mQueryHandler.startUpdate(0, null, CalendarAlerts.CONTENT_URI, values, 94 selection, null /* selectionArgs */, Utils.UNDO_DELAY); 95 } 96 97 private void dismissAlarm(long id) { 98 ContentValues values = new ContentValues(1 /* size */); 99 values.put(PROJECTION[INDEX_STATE], CalendarAlerts.STATE_DISMISSED); 100 String selection = CalendarAlerts._ID + "=" + id; 101 mQueryHandler.startUpdate(0, null, CalendarAlerts.CONTENT_URI, values, 102 selection, null /* selectionArgs */, Utils.UNDO_DELAY); 103 } 104 105 private class QueryHandler extends AsyncQueryService { 106 public QueryHandler(Context context) { 107 super(context); 108 } 109 110 @Override 111 protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 112 // Only set mCursor if the Activity is not finishing. Otherwise close the cursor. 113 if (!isFinishing()) { 114 mCursor = cursor; 115 mAdapter.changeCursor(cursor); 116 mListView.setSelection(cursor.getCount() - 1); 117 118 // The results are in, enable the buttons 119 mDismissAllButton.setEnabled(true); 120 } else { 121 cursor.close(); 122 } 123 } 124 125 @Override 126 protected void onInsertComplete(int token, Object cookie, Uri uri) { 127 if (uri != null) { 128 Long alarmTime = (Long) cookie; 129 130 if (alarmTime != 0) { 131 // Set a new alarm to go off after the snooze delay. 132 // TODO make provider schedule this automatically when 133 // inserting an alarm 134 AlertUtils.scheduleAlarm(AlertActivity.this, null, alarmTime); 135 } 136 } 137 } 138 139 @Override 140 protected void onUpdateComplete(int token, Object cookie, int result) { 141 // Ignore 142 } 143 } 144 145 146 147 private final OnItemClickListener mViewListener = new OnItemClickListener() { 148 149 @Override 150 public void onItemClick(AdapterView<?> parent, View view, int position, 151 long i) { 152 AlertActivity alertActivity = AlertActivity.this; 153 Cursor cursor = alertActivity.getItemForView(view); 154 155 // Mark this alarm as DISMISSED 156 dismissAlarm(cursor.getLong(INDEX_ROW_ID)); 157 158 // build an intent and task stack to start EventInfoActivity with AllInOneActivity 159 // as the parent activity rooted to home. 160 long id = cursor.getInt(AlertActivity.INDEX_EVENT_ID); 161 long startMillis = cursor.getLong(AlertActivity.INDEX_BEGIN); 162 long endMillis = cursor.getLong(AlertActivity.INDEX_END); 163 Intent eventIntent = AlertUtils.buildEventViewIntent(AlertActivity.this, id, 164 startMillis, endMillis); 165 166 TaskStackBuilder.create(AlertActivity.this) 167 .addParentStack(EventInfoActivity.class).addNextIntent(eventIntent) 168 .startActivities(); 169 170 alertActivity.finish(); 171 } 172 }; 173 174 @Override 175 protected void onCreate(Bundle icicle) { 176 super.onCreate(icicle); 177 178 setContentView(R.layout.alert_activity); 179 setTitle(R.string.past_alerts_title); 180 181 mQueryHandler = new QueryHandler(this); 182 mAdapter = new AlertAdapter(this, R.layout.alert_item); 183 184 mListView = (ListView) findViewById(R.id.alert_container); 185 mListView.setItemsCanFocus(true); 186 mListView.setAdapter(mAdapter); 187 mListView.setOnItemClickListener(mViewListener); 188 189 mDismissAllButton = (Button) findViewById(R.id.dismiss_all); 190 mDismissAllButton.setOnClickListener(this); 191 192 // Disable the buttons, since they need mCursor, which is created asynchronously 193 mDismissAllButton.setEnabled(false); 194 } 195 196 @Override 197 protected void onResume() { 198 super.onResume(); 199 200 // If the cursor is null, start the async handler. If it is not null just requery. 201 if (mCursor == null) { 202 Uri uri = CalendarAlerts.CONTENT_URI_BY_INSTANCE; 203 String[] selectionArgs = new String[] { 204 Integer.toString(CalendarAlerts.STATE_FIRED), 205 Long.toString(System.currentTimeMillis()) 206 }; 207 mQueryHandler.startQuery(0, null, uri, PROJECTION, SELECTION, selectionArgs, 208 CalendarContract.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, false); 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 == mDismissAllButton) { 239 NotificationManager nm = 240 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 241 nm.cancel(AlertUtils.EXPIRED_GROUP_NOTIFICATION_ID); 242 243 dismissFiredAlarmsForPastEvents(); 244 245 finish(); 246 } 247 } 248 249 public boolean isEmpty() { 250 return mCursor != null ? (mCursor.getCount() == 0) : true; 251 } 252 253 public Cursor getItemForView(View view) { 254 final int index = mListView.getPositionForView(view); 255 if (index < 0) { 256 return null; 257 } 258 return (Cursor) mListView.getAdapter().getItem(index); 259 } 260} 261