1146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project/*
2146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *
4146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * you may not use this file except in compliance with the License.
6146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * You may obtain a copy of the License at
7146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *
8146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project *
10146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * See the License for the specific language governing permissions and
14146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * limitations under the License.
15146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project */
16146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
1723e7da3eacee7bceb105cdfc7b5329c7a43846d5Mason Tangpackage com.android.calendar.alerts;
18146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
1907d9fee87bc02849c0dd7b66326a320d53cf5479Michael Chanimport com.android.calendar.AllInOneActivity;
2023e7da3eacee7bceb105cdfc7b5329c7a43846d5Mason Tangimport com.android.calendar.AsyncQueryService;
2123e7da3eacee7bceb105cdfc7b5329c7a43846d5Mason Tangimport com.android.calendar.R;
2223e7da3eacee7bceb105cdfc7b5329c7a43846d5Mason Tangimport com.android.calendar.Utils;
23146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
24146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.app.Activity;
25146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.app.AlarmManager;
26146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.app.NotificationManager;
27fa292a0db2a6f04255c75a57908b17ba48a96183RoboErikimport android.app.PendingIntent;
28fa292a0db2a6f04255c75a57908b17ba48a96183RoboErikimport android.content.ContentUris;
295c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chanimport android.content.ContentValues;
30146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.content.Context;
31db4ce4a81063b7f5f6068f4144f8a3e3bca1e064Erikimport android.content.Intent;
32146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.database.Cursor;
33146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.net.Uri;
34db4ce4a81063b7f5f6068f4144f8a3e3bca1e064Erikimport android.net.Uri.Builder;
35146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.os.Bundle;
36a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract;
37a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErikimport android.provider.CalendarContract.CalendarAlerts;
381a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawaimport android.util.Log;
39146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.view.View;
401a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawaimport android.view.View.OnClickListener;
41146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.AdapterView;
421a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawaimport android.widget.AdapterView.OnItemClickListener;
43146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.Button;
44146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Projectimport android.widget.ListView;
45146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
46146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project/**
47146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * The alert panel that pops up when there is a calendar event alarm.
48146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project * This activity is started by an intent that specifies an event id.
49146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project  */
501a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawapublic class AlertActivity extends Activity implements OnClickListener {
511a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa    private static final String TAG = "AlertActivity";
525c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
53146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // The default snooze delay: 5 minutes
54146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final long SNOOZE_DELAY = 5 * 60 * 1000L;
555c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
565c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan    private static final String[] PROJECTION = new String[] {
57146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        CalendarAlerts._ID,              // 0
58146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        CalendarAlerts.TITLE,            // 1
59146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        CalendarAlerts.EVENT_LOCATION,   // 2
60146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        CalendarAlerts.ALL_DAY,          // 3
61146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        CalendarAlerts.BEGIN,            // 4
62146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        CalendarAlerts.END,              // 5
63146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        CalendarAlerts.EVENT_ID,         // 6
640e1e62408b96e1532eb6f6a609ae4c817751aaf3RoboErik        CalendarAlerts.CALENDAR_COLOR,            // 7
65146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        CalendarAlerts.RRULE,            // 8
66146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        CalendarAlerts.HAS_ALARM,        // 9
67146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        CalendarAlerts.STATE,            // 10
68146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        CalendarAlerts.ALARM_TIME,       // 11
69146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    };
705c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
715c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan    public static final int INDEX_ROW_ID = 0;
72146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final int INDEX_TITLE = 1;
73146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final int INDEX_EVENT_LOCATION = 2;
74146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final int INDEX_ALL_DAY = 3;
75146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final int INDEX_BEGIN = 4;
76146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final int INDEX_END = 5;
77146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final int INDEX_EVENT_ID = 6;
78146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final int INDEX_COLOR = 7;
79146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final int INDEX_RRULE = 8;
80146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final int INDEX_HAS_ALARM = 9;
81146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final int INDEX_STATE = 10;
82146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final int INDEX_ALARM_TIME = 11;
835c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
84e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan    private static final String SELECTION = CalendarAlerts.STATE + "=?";
85e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan    private static final String[] SELECTIONARG = new String[] {
86fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        Integer.toString(CalendarAlerts.STATE_FIRED)
87e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan    };
88e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan
89146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // We use one notification id for all events so that we don't clutter
90146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // the notification screen.  It doesn't matter what the id is, as long
91146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    // as it is used consistently everywhere.
92146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public static final int NOTIFICATION_ID = 0;
935c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
94146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private AlertAdapter mAdapter;
95146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private QueryHandler mQueryHandler;
96146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private Cursor mCursor;
97146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private ListView mListView;
98146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private Button mSnoozeAllButton;
99146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private Button mDismissAllButton;
1005c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
1015c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
1025c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan    private void dismissFiredAlarms() {
1035c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        ContentValues values = new ContentValues(1 /* size */);
104fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        values.put(PROJECTION[INDEX_STATE], CalendarAlerts.STATE_DISMISSED);
105fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        String selection = CalendarAlerts.STATE + "=" + CalendarAlerts.STATE_FIRED;
1065c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        mQueryHandler.startUpdate(0, null, CalendarAlerts.CONTENT_URI, values,
107bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                selection, null /* selectionArgs */, Utils.UNDO_DELAY);
1085c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan    }
1095c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
1105c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan    private void dismissAlarm(long id) {
1115c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        ContentValues values = new ContentValues(1 /* size */);
112fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        values.put(PROJECTION[INDEX_STATE], CalendarAlerts.STATE_DISMISSED);
1135c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        String selection = CalendarAlerts._ID + "=" + id;
1145c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        mQueryHandler.startUpdate(0, null, CalendarAlerts.CONTENT_URI, values,
115bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan                selection, null /* selectionArgs */, Utils.UNDO_DELAY);
1165c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan    }
1175c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
118bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan    private class QueryHandler extends AsyncQueryService {
119bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        public QueryHandler(Context context) {
120bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan            super(context);
121146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
122146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
123146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        @Override
124146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
125146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            // Only set mCursor if the Activity is not finishing. Otherwise close the cursor.
126146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            if (!isFinishing()) {
127146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                mCursor = cursor;
128146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                mAdapter.changeCursor(cursor);
12910d9f11fec9cb578185e4455eeaef289c0dff8b9Michael Chan                mListView.setSelection(cursor.getCount() - 1);
1305c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
131146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                // The results are in, enable the buttons
132146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                mSnoozeAllButton.setEnabled(true);
133146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                mDismissAllButton.setEnabled(true);
134146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            } else {
135146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                cursor.close();
136146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
137146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
1385c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
1395c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        @Override
1405c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        protected void onInsertComplete(int token, Object cookie, Uri uri) {
1415c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan            if (uri != null) {
142e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan                Long alarmTime = (Long) cookie;
143e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan
144e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan                if (alarmTime != 0) {
145e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan                    // Set a new alarm to go off after the snooze delay.
146fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik                    // TODO make provider schedule this automatically when
147fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik                    // inserting an alarm
148e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan                    AlarmManager alarmManager =
149e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan                            (AlarmManager) getSystemService(Context.ALARM_SERVICE);
150fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik                    scheduleAlarm(AlertActivity.this, alarmManager, alarmTime);
151e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan                }
1525c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan            }
1535c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        }
1545c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
1555c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        @Override
1565c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        protected void onUpdateComplete(int token, Object cookie, int result) {
1575c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan            // Ignore
1585c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        }
1595c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan    }
1605c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
161fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik    /**
162fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik     * Schedules an alarm intent with the system AlarmManager that will notify
163fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik     * listeners when a reminder should be fired. The provider will keep
164fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik     * scheduled reminders up to date but apps may use this to implement snooze
165fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik     * functionality without modifying the reminders table. Scheduled alarms
166fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik     * will generate an intent using {@link #ACTION_EVENT_REMINDER}.
167fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik     *
168fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik     * @param context A context for referencing system resources
169fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik     * @param manager The AlarmManager to use or null
170fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik     * @param alarmTime The time to fire the intent in UTC millis since epoch
171fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik     */
172fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik    public static void scheduleAlarm(Context context, AlarmManager manager, long alarmTime) {
173fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik
174fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        if (manager == null) {
175fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik            manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
176fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        }
177fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik
178fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        Intent intent = new Intent(CalendarContract.ACTION_EVENT_REMINDER);
179fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        intent.setData(ContentUris.withAppendedId(CalendarContract.CONTENT_URI, alarmTime));
180fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        intent.putExtra(CalendarContract.CalendarAlerts.ALARM_TIME, alarmTime);
181fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
182fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        manager.set(AlarmManager.RTC_WAKEUP, alarmTime, pi);
183fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik    }
184fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik
1855c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan    private static ContentValues makeContentValues(long eventId, long begin, long end,
1865c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan            long alarmTime, int minutes) {
1875c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        ContentValues values = new ContentValues();
1885c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        values.put(CalendarAlerts.EVENT_ID, eventId);
1895c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        values.put(CalendarAlerts.BEGIN, begin);
1905c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        values.put(CalendarAlerts.END, end);
1915c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        values.put(CalendarAlerts.ALARM_TIME, alarmTime);
1925c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        long currentTime = System.currentTimeMillis();
1935c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        values.put(CalendarAlerts.CREATION_TIME, currentTime);
1945c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        values.put(CalendarAlerts.RECEIVED_TIME, 0);
1955c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        values.put(CalendarAlerts.NOTIFY_TIME, 0);
196fa292a0db2a6f04255c75a57908b17ba48a96183RoboErik        values.put(CalendarAlerts.STATE, CalendarAlerts.STATE_SCHEDULED);
1975c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        values.put(CalendarAlerts.MINUTES, minutes);
1985c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan        return values;
199146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
2005c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
201146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    private OnItemClickListener mViewListener = new OnItemClickListener() {
202146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
2034ce500bd7d08eac3f05dfd50bce51e620fa9f08eChristian Mehlmauer        public void onItemClick(AdapterView<?> parent, View view, int position,
204146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                long i) {
205146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            AlertActivity alertActivity = AlertActivity.this;
206146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Cursor cursor = alertActivity.getItemForView(view);
2075c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
2089e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan            // Mark this alarm as DISMISSED
2099e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan            dismissAlarm(cursor.getLong(INDEX_ROW_ID));
2109e89dca0902d13fe27fd2680cc15cbb470e40288Michael Chan
211146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            long id = cursor.getInt(AlertActivity.INDEX_EVENT_ID);
212146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            long startMillis = cursor.getLong(AlertActivity.INDEX_BEGIN);
213146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            long endMillis = cursor.getLong(AlertActivity.INDEX_END);
214db4ce4a81063b7f5f6068f4144f8a3e3bca1e064Erik            Intent eventIntent = new Intent(Intent.ACTION_VIEW);
215a7c0390d9c5dd4ff730de505682687fae5f5ced0RoboErik            Builder builder = CalendarContract.CONTENT_URI.buildUpon();
216d050fc8acd93f59ecff1536572b85d84a08335acRoboErik            builder.appendEncodedPath("events/" + id);
217db4ce4a81063b7f5f6068f4144f8a3e3bca1e064Erik            eventIntent.setData(builder.build());
21807d9fee87bc02849c0dd7b66326a320d53cf5479Michael Chan            eventIntent.setClass(AlertActivity.this, AllInOneActivity.class);
219a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            eventIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startMillis);
220a27a886892fe3ec5edbc63c0b58e0a988623011aRoboErik            eventIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endMillis);
221db4ce4a81063b7f5f6068f4144f8a3e3bca1e064Erik            alertActivity.startActivity(eventIntent);
2225c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
223146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            alertActivity.finish();
224146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
225146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    };
2265c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
227146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
228146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    protected void onCreate(Bundle icicle) {
229146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        super.onCreate(icicle);
2305c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
231146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        setContentView(R.layout.alert_activity);
2327abd8566e5718c43d610e046495bcb412e87847fThe Android Open Source Project        setTitle(R.string.alert_title);
2335c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
234bed0275111ecc6c4a3a638f90a9bac13bee594f4Michael Chan        mQueryHandler = new QueryHandler(this);
235146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mAdapter = new AlertAdapter(this, R.layout.alert_item);
2365c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
237146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mListView = (ListView) findViewById(R.id.alert_container);
238146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mListView.setItemsCanFocus(true);
239146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mListView.setAdapter(mAdapter);
240146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mListView.setOnItemClickListener(mViewListener);
2415c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
242146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mSnoozeAllButton = (Button) findViewById(R.id.snooze_all);
2431a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa        mSnoozeAllButton.setOnClickListener(this);
244146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mDismissAllButton = (Button) findViewById(R.id.dismiss_all);
2451a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa        mDismissAllButton.setOnClickListener(this);
246146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project
247146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // Disable the buttons, since they need mCursor, which is created asynchronously
248146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mSnoozeAllButton.setEnabled(false);
249146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        mDismissAllButton.setEnabled(false);
250146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
2515c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
252146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
253146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    protected void onResume() {
254146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        super.onResume();
2555c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
256146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        // If the cursor is null, start the async handler. If it is not null just requery.
257146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mCursor == null) {
258146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            Uri uri = CalendarAlerts.CONTENT_URI_BY_INSTANCE;
259e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan            mQueryHandler.startQuery(0, null, uri, PROJECTION, SELECTION,
260e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan                    SELECTIONARG, CalendarAlerts.DEFAULT_SORT_ORDER);
261146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        } else {
2621a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa            if (!mCursor.requery()) {
2631a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                Log.w(TAG, "Cursor#requery() failed.");
2641a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                mCursor.close();
2651a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                mCursor = null;
2661a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa            }
267146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
268146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
2695c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
270146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
271146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    protected void onStop() {
272146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        super.onStop();
273e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan        AlertService.updateAlertNotification(this);
2745c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
275146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mCursor != null) {
276146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mCursor.deactivate();
277146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
278146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
2795c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
280146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    @Override
281146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    protected void onDestroy() {
282146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        super.onDestroy();
283146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (mCursor != null) {
284146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            mCursor.close();
285146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
286146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
2875c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
2881a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa    @Override
2891a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa    public void onClick(View v) {
2901a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa        if (v == mSnoozeAllButton) {
2915c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan            long alarmTime = System.currentTimeMillis() + SNOOZE_DELAY;
2925c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
293146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            NotificationManager nm =
294146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
295146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            nm.cancel(NOTIFICATION_ID);
296e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan
2971a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa            if (mCursor != null) {
2981a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                long scheduleAlarmTime = 0;
2991a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                mCursor.moveToPosition(-1);
3001a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                while (mCursor.moveToNext()) {
3011a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                    long eventId = mCursor.getLong(INDEX_EVENT_ID);
3021a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                    long begin = mCursor.getLong(INDEX_BEGIN);
3031a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                    long end = mCursor.getLong(INDEX_END);
3041a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa
3051a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                    // Set the "minutes" to zero to indicate this is a snoozed
3061a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                    // alarm.  There is code in AlertService.java that checks
3071a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                    // this field.
3081a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                    ContentValues values =
3091a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                            makeContentValues(eventId, begin, end, alarmTime, 0 /* minutes */);
3101a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa
3111a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                    // Create a new alarm entry in the CalendarAlerts table
3121a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                    if (mCursor.isLast()) {
3131a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                        scheduleAlarmTime = alarmTime;
3141a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                    }
3151a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                    mQueryHandler.startInsert(0,
3161a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                            scheduleAlarmTime, CalendarAlerts.CONTENT_URI, values,
3171a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                            Utils.UNDO_DELAY);
318e2ae1ef8decfddcc4e5802483e92cab93c6fc67cMichael Chan                }
3191a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa            } else {
3201a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa                Log.d(TAG, "Cursor object is null. Ignore the Snooze request.");
321146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            }
3225c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
3235c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan            dismissFiredAlarms();
324146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            finish();
3251a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa        } else if (v == mDismissAllButton) {
326146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            NotificationManager nm =
327146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
328146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            nm.cancel(NOTIFICATION_ID);
3295c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
3305c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan            dismissFiredAlarms();
3315c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
332146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            finish();
333146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
3341a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa    }
3355c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
336146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public boolean isEmpty() {
3371a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa        return mCursor != null ? (mCursor.getCount() == 0) : true;
338146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
3395c7290c760979b1a43acfb6d90d6216d0e0a0934Michael Chan
340146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    public Cursor getItemForView(View view) {
3411a7fa28f2ac6bd293bb4009d22f3f1426e7658c3Daisuke Miyakawa        final int index = mListView.getPositionForView(view);
342146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        if (index < 0) {
343146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project            return null;
344146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        }
345146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project        return (Cursor) mListView.getAdapter().getItem(index);
346146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project    }
347146de36083f6ce8b7e8a1f974d3990594a36bfecThe Android Open Source Project}
348