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 17 package com.android.calendar.alerts; 18 19 import android.app.Activity; 20 import android.app.NotificationManager; 21 import android.app.TaskStackBuilder; 22 import android.content.ContentValues; 23 import android.content.Context; 24 import android.content.Intent; 25 import android.database.Cursor; 26 import android.net.Uri; 27 import android.os.Bundle; 28 import android.provider.CalendarContract; 29 import android.provider.CalendarContract.CalendarAlerts; 30 import android.util.Log; 31 import android.view.View; 32 import android.view.View.OnClickListener; 33 import android.widget.AdapterView; 34 import android.widget.AdapterView.OnItemClickListener; 35 import android.widget.Button; 36 import android.widget.ListView; 37 38 import com.android.calendar.AsyncQueryService; 39 import com.android.calendar.EventInfoActivity; 40 import com.android.calendar.R; 41 import 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 */ 47 public 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 mDismissAllButton; 88 89 dismissFiredAlarms()90 private void dismissFiredAlarms() { 91 ContentValues values = new ContentValues(1 /* size */); 92 values.put(PROJECTION[INDEX_STATE], CalendarAlerts.STATE_DISMISSED); 93 String selection = CalendarAlerts.STATE + "=" + CalendarAlerts.STATE_FIRED; 94 mQueryHandler.startUpdate(0, null, CalendarAlerts.CONTENT_URI, values, 95 selection, null /* selectionArgs */, Utils.UNDO_DELAY); 96 } 97 dismissAlarm(long id)98 private void dismissAlarm(long id) { 99 ContentValues values = new ContentValues(1 /* size */); 100 values.put(PROJECTION[INDEX_STATE], CalendarAlerts.STATE_DISMISSED); 101 String selection = CalendarAlerts._ID + "=" + id; 102 mQueryHandler.startUpdate(0, null, CalendarAlerts.CONTENT_URI, values, 103 selection, null /* selectionArgs */, Utils.UNDO_DELAY); 104 } 105 106 private class QueryHandler extends AsyncQueryService { QueryHandler(Context context)107 public QueryHandler(Context context) { 108 super(context); 109 } 110 111 @Override onQueryComplete(int token, Object cookie, Cursor cursor)112 protected void onQueryComplete(int token, Object cookie, Cursor cursor) { 113 // Only set mCursor if the Activity is not finishing. Otherwise close the cursor. 114 if (!isFinishing()) { 115 mCursor = cursor; 116 mAdapter.changeCursor(cursor); 117 mListView.setSelection(cursor.getCount() - 1); 118 119 // The results are in, enable the buttons 120 mDismissAllButton.setEnabled(true); 121 } else { 122 cursor.close(); 123 } 124 } 125 126 @Override onUpdateComplete(int token, Object cookie, int result)127 protected void onUpdateComplete(int token, Object cookie, int result) { 128 // Ignore 129 } 130 } 131 132 private final OnItemClickListener mViewListener = new OnItemClickListener() { 133 134 @Override 135 public void onItemClick(AdapterView<?> parent, View view, int position, 136 long i) { 137 AlertActivity alertActivity = AlertActivity.this; 138 Cursor cursor = alertActivity.getItemForView(view); 139 140 // Mark this alarm as DISMISSED 141 dismissAlarm(cursor.getLong(INDEX_ROW_ID)); 142 143 // build an intent and task stack to start EventInfoActivity with AllInOneActivity 144 // as the parent activity rooted to home. 145 long id = cursor.getInt(AlertActivity.INDEX_EVENT_ID); 146 long startMillis = cursor.getLong(AlertActivity.INDEX_BEGIN); 147 long endMillis = cursor.getLong(AlertActivity.INDEX_END); 148 Intent eventIntent = AlertUtils.buildEventViewIntent(AlertActivity.this, id, 149 startMillis, endMillis); 150 151 if (Utils.isJellybeanOrLater()) { 152 TaskStackBuilder.create(AlertActivity.this).addParentStack(EventInfoActivity.class) 153 .addNextIntent(eventIntent).startActivities(); 154 } else { 155 alertActivity.startActivity(eventIntent); 156 } 157 158 alertActivity.finish(); 159 } 160 }; 161 162 @Override onCreate(Bundle icicle)163 protected void onCreate(Bundle icicle) { 164 super.onCreate(icicle); 165 166 setContentView(R.layout.alert_activity); 167 setTitle(R.string.alert_title); 168 169 mQueryHandler = new QueryHandler(this); 170 mAdapter = new AlertAdapter(this, R.layout.alert_item); 171 172 mListView = (ListView) findViewById(R.id.alert_container); 173 mListView.setItemsCanFocus(true); 174 mListView.setAdapter(mAdapter); 175 mListView.setOnItemClickListener(mViewListener); 176 177 mDismissAllButton = (Button) findViewById(R.id.dismiss_all); 178 mDismissAllButton.setOnClickListener(this); 179 180 // Disable the buttons, since they need mCursor, which is created asynchronously 181 mDismissAllButton.setEnabled(false); 182 } 183 184 @Override onResume()185 protected void onResume() { 186 super.onResume(); 187 188 // If the cursor is null, start the async handler. If it is not null just requery. 189 if (mCursor == null) { 190 Uri uri = CalendarAlerts.CONTENT_URI_BY_INSTANCE; 191 mQueryHandler.startQuery(0, null, uri, PROJECTION, SELECTION, SELECTIONARG, 192 CalendarContract.CalendarAlerts.DEFAULT_SORT_ORDER); 193 } else { 194 if (!mCursor.requery()) { 195 Log.w(TAG, "Cursor#requery() failed."); 196 mCursor.close(); 197 mCursor = null; 198 } 199 } 200 } 201 closeActivityIfEmpty()202 void closeActivityIfEmpty() { 203 if (mCursor != null && !mCursor.isClosed() && mCursor.getCount() == 0) { 204 AlertActivity.this.finish(); 205 } 206 } 207 208 @Override onStop()209 protected void onStop() { 210 super.onStop(); 211 AlertService.updateAlertNotification(this); 212 213 if (mCursor != null) { 214 mCursor.deactivate(); 215 } 216 } 217 218 @Override onDestroy()219 protected void onDestroy() { 220 super.onDestroy(); 221 if (mCursor != null) { 222 mCursor.close(); 223 } 224 } 225 226 @Override onClick(View v)227 public void onClick(View v) { 228 if (v == mDismissAllButton) { 229 NotificationManager nm = 230 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); 231 nm.cancelAll(); 232 233 dismissFiredAlarms(); 234 235 finish(); 236 } 237 } 238 isEmpty()239 public boolean isEmpty() { 240 return mCursor != null ? (mCursor.getCount() == 0) : true; 241 } 242 getItemForView(View view)243 public Cursor getItemForView(View view) { 244 final int index = mListView.getPositionForView(view); 245 if (index < 0) { 246 return null; 247 } 248 return (Cursor) mListView.getAdapter().getItem(index); 249 } 250 } 251