Home | History | Annotate | Download | only in alerts
      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 
     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 
     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 {
    107         public QueryHandler(Context context) {
    108             super(context);
    109         }
    110 
    111         @Override
    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
    127         protected void onInsertComplete(int token, Object cookie, Uri uri) {
    128             if (uri != null) {
    129                 Long alarmTime = (Long) cookie;
    130 
    131                 if (alarmTime != 0) {
    132                     // Set a new alarm to go off after the snooze delay.
    133                     // TODO make provider schedule this automatically when
    134                     // inserting an alarm
    135                     AlertUtils.scheduleAlarm(AlertActivity.this, null, alarmTime);
    136                 }
    137             }
    138         }
    139 
    140         @Override
    141         protected void onUpdateComplete(int token, Object cookie, int result) {
    142             // Ignore
    143         }
    144     }
    145 
    146 
    147 
    148     private final OnItemClickListener mViewListener = new OnItemClickListener() {
    149 
    150         @Override
    151         public void onItemClick(AdapterView<?> parent, View view, int position,
    152                 long i) {
    153             AlertActivity alertActivity = AlertActivity.this;
    154             Cursor cursor = alertActivity.getItemForView(view);
    155 
    156             // Mark this alarm as DISMISSED
    157             dismissAlarm(cursor.getLong(INDEX_ROW_ID));
    158 
    159             // build an intent and task stack to start EventInfoActivity with AllInOneActivity
    160             // as the parent activity rooted to home.
    161             long id = cursor.getInt(AlertActivity.INDEX_EVENT_ID);
    162             long startMillis = cursor.getLong(AlertActivity.INDEX_BEGIN);
    163             long endMillis = cursor.getLong(AlertActivity.INDEX_END);
    164             Intent eventIntent = AlertUtils.buildEventViewIntent(AlertActivity.this, id,
    165                     startMillis, endMillis);
    166 
    167             TaskStackBuilder.create(AlertActivity.this)
    168                     .addParentStack(EventInfoActivity.class).addNextIntent(eventIntent)
    169                     .startActivities();
    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         mDismissAllButton = (Button) findViewById(R.id.dismiss_all);
    191         mDismissAllButton.setOnClickListener(this);
    192 
    193         // Disable the buttons, since they need mCursor, which is created asynchronously
    194         mDismissAllButton.setEnabled(false);
    195     }
    196 
    197     @Override
    198     protected void onResume() {
    199         super.onResume();
    200 
    201         // If the cursor is null, start the async handler. If it is not null just requery.
    202         if (mCursor == null) {
    203             Uri uri = CalendarAlerts.CONTENT_URI_BY_INSTANCE;
    204             mQueryHandler.startQuery(0, null, uri, PROJECTION, SELECTION, SELECTIONARG,
    205                     CalendarContract.CalendarAlerts.DEFAULT_SORT_ORDER);
    206         } else {
    207             if (!mCursor.requery()) {
    208                 Log.w(TAG, "Cursor#requery() failed.");
    209                 mCursor.close();
    210                 mCursor = null;
    211             }
    212         }
    213     }
    214 
    215     @Override
    216     protected void onStop() {
    217         super.onStop();
    218         AlertService.updateAlertNotification(this);
    219 
    220         if (mCursor != null) {
    221             mCursor.deactivate();
    222         }
    223     }
    224 
    225     @Override
    226     protected void onDestroy() {
    227         super.onDestroy();
    228         if (mCursor != null) {
    229             mCursor.close();
    230         }
    231     }
    232 
    233     @Override
    234     public void onClick(View v) {
    235         if (v == mDismissAllButton) {
    236             NotificationManager nm =
    237                 (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    238             nm.cancelAll();
    239 
    240             dismissFiredAlarms();
    241 
    242             finish();
    243         }
    244     }
    245 
    246     public boolean isEmpty() {
    247         return mCursor != null ? (mCursor.getCount() == 0) : true;
    248     }
    249 
    250     public Cursor getItemForView(View view) {
    251         final int index = mListView.getPositionForView(view);
    252         if (index < 0) {
    253             return null;
    254         }
    255         return (Cursor) mListView.getAdapter().getItem(index);
    256     }
    257 }
    258