Alarms.java revision 232725e8c1b1b85a44857cedcc842dcd2c956dc2
15fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project/* 25fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project 35fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * 45fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 55fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * you may not use this file except in compliance with the License. 65fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * You may obtain a copy of the License at 75fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * 85fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 95fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * 105fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * See the License for the specific language governing permissions and 145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * limitations under the License. 155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 17fa954248b41b567dfa2ddd7bd063d3936a51758eDaniel Sandlerpackage com.android.deskclock; 185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.app.AlarmManager; 20c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scottimport android.app.NotificationManager; 215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.app.PendingIntent; 225fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.ContentResolver; 235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.ContentValues; 245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.ContentUris; 255fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Context; 265fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Intent; 275fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.SharedPreferences; 285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.database.Cursor; 295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.net.Uri; 30d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scottimport android.os.Parcel; 315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.provider.Settings; 325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.text.format.DateFormat; 335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 345fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport java.util.Calendar; 35eb142ac59aa8039c409b5fe4f50a130f16960d41Eric Fischerimport java.text.DateFormatSymbols; 365fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 375fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project/** 385fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * The Alarms provider supplies info about Alarm Clock settings 395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectpublic class Alarms { 415fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 42d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This action triggers the AlarmReceiver as well as the AlarmKlaxon. It 43d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // is a public action used in the manifest for receiving Alarm broadcasts 44d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // from the alarm manager. 45fa954248b41b567dfa2ddd7bd063d3936a51758eDaniel Sandler public static final String ALARM_ALERT_ACTION = "com.android.deskclock.ALARM_ALERT"; 465fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 47d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This is a private action used by the AlarmKlaxon to update the UI to 48d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // show the alarm has been killed. 49d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String ALARM_KILLED = "alarm_killed"; 505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 51d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // Extra in the ALARM_KILLED intent to indicate to the user how long the 52d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // alarm played before being killed. 53d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String ALARM_KILLED_TIMEOUT = "alarm_killed_timeout"; 545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 55d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This string is used to indicate a silent alarm in the db. 56d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String ALARM_ALERT_SILENT = "silent"; 575fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 58d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This intent is sent from the notification when the user cancels the 59d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // snooze alert. 60d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String CANCEL_SNOOZE = "cancel_snooze"; 615fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 62d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This string is used when passing an Alarm object through an intent. 63d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String ALARM_INTENT_EXTRA = "intent.extra.alarm"; 645fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 65d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This extra is the raw Alarm object data. It is used in the 66d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // AlarmManagerService to avoid a ClassNotFoundException when filling in 67d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // the Intent extras. 68d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String ALARM_RAW_DATA = "intent.extra.alarm_raw"; 695fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 70d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This string is used to identify the alarm id passed to SetAlarm from the 71d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // list of alarms. 72d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String ALARM_ID = "alarm_id"; 735fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 74d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott final static String PREF_SNOOZE_ID = "snooze_id"; 75d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott final static String PREF_SNOOZE_TIME = "snooze_time"; 765fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 77d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private final static String DM12 = "E h:mm aa"; 78d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private final static String DM24 = "E k:mm"; 795fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 80d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private final static String M12 = "h:mm aa"; 811ebd23eaa82ab560f5c7d8aeca8df7512df8424ePatrick Scott // Shared with DigitalClock 821ebd23eaa82ab560f5c7d8aeca8df7512df8424ePatrick Scott final static String M24 = "kk:mm"; 835fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 845fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 855fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Creates a new Alarm. 865fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 87e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott public static long addAlarm(Context context, Alarm alarm) { 88e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott ContentValues values = createContentValues(alarm); 89e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott context.getContentResolver().insert(Alarm.Columns.CONTENT_URI, values); 90e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 91e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott long timeInMillis = calculateAlarm(alarm); 92e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott if (alarm.enabled) { 93e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott clearSnoozeIfNeeded(context, timeInMillis); 94e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott } 95e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott setNextAlert(context); 96e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott return timeInMillis; 975fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 985fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 995fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 1005fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Removes an existing Alarm. If this alarm is snoozing, disables 1015fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * snooze. Sets next alert. 1025fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 103d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static void deleteAlarm( 1045fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Context context, int alarmId) { 1055fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 1065fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project ContentResolver contentResolver = context.getContentResolver(); 1075fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /* If alarm is snoozing, lose it */ 108d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott disableSnoozeAlert(context, alarmId); 1095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 110d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Uri uri = ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarmId); 111d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott contentResolver.delete(uri, "", null); 1125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 1135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project setNextAlert(context); 1145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 1155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 1165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 1175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Queries all alarms 1185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * @return cursor over all alarms 1195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 120d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static Cursor getAlarmsCursor(ContentResolver contentResolver) { 1215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return contentResolver.query( 122d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm.Columns.CONTENT_URI, Alarm.Columns.ALARM_QUERY_COLUMNS, 123d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott null, null, Alarm.Columns.DEFAULT_SORT_ORDER); 1245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 1255fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 126d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // Private method to get a more limited set of alarms from the database. 127d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private static Cursor getFilteredAlarmsCursor( 128d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott ContentResolver contentResolver) { 129d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott return contentResolver.query(Alarm.Columns.CONTENT_URI, 130d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm.Columns.ALARM_QUERY_COLUMNS, Alarm.Columns.WHERE_ENABLED, 131d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott null, null); 1325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 1335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 134e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott private static ContentValues createContentValues(Alarm alarm) { 135e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott ContentValues values = new ContentValues(8); 136e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott // Set the alarm_time value if this alarm does not repeat. This will be 137e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott // used later to disable expire alarms. 138e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott long time = 0; 139e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott if (!alarm.daysOfWeek.isRepeatSet()) { 140e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott time = calculateAlarm(alarm); 141e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott } 142e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 143e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.ENABLED, alarm.enabled ? 1 : 0); 144e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.HOUR, alarm.hour); 145e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.MINUTES, alarm.minutes); 146e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.ALARM_TIME, alarm.time); 147e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.DAYS_OF_WEEK, alarm.daysOfWeek.getCoded()); 148e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.VIBRATE, alarm.vibrate); 149e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.MESSAGE, alarm.label); 150e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 151e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott // A null alert Uri indicates a silent alarm. 152e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.ALERT, alarm.alert == null ? ALARM_ALERT_SILENT 153e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott : alarm.alert.toString()); 154e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 155e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott return values; 156e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott } 157e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 158e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott private static void clearSnoozeIfNeeded(Context context, long alarmTime) { 159e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott // If this alarm fires before the next snooze, clear the snooze to 160e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott // enable this alarm. 161e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott SharedPreferences prefs = 162e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott context.getSharedPreferences(AlarmClock.PREFERENCES, 0); 163e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott long snoozeTime = prefs.getLong(PREF_SNOOZE_TIME, 0); 164e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott if (alarmTime < snoozeTime) { 165e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott clearSnoozePreference(context, prefs); 166e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott } 167e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott } 168e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 1695fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 170d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott * Return an Alarm object representing the alarm id in the database. 171d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott * Returns null if no alarm exists. 1725fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 173d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static Alarm getAlarm(ContentResolver contentResolver, int alarmId) { 1745fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Cursor cursor = contentResolver.query( 175d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarmId), 176d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm.Columns.ALARM_QUERY_COLUMNS, 177d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott null, null, null); 178d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm alarm = null; 179d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (cursor != null) { 180d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (cursor.moveToFirst()) { 181d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott alarm = new Alarm(cursor); 182d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 183d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott cursor.close(); 184d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 185d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott return alarm; 1865fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 1875fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 1885fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 1895fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 1905fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * A convenience method to set an alarm in the Alarms 1915fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * content provider. 192c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott * @return Time when the alarm will fire. 1935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 194e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott public static long setAlarm(Context context, Alarm alarm) { 195e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott ContentValues values = createContentValues(alarm); 1965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project ContentResolver resolver = context.getContentResolver(); 197e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott resolver.update( 198e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarm.id), 199e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values, null, null); 2005fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 201e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott long timeInMillis = calculateAlarm(alarm); 202c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott 203e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott if (alarm.enabled) { 204232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // Disable the snooze if we just changed the snoozed alarm. This 205232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // only does work if the snoozed alarm is the same as the given 206232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // alarm. 207232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // TODO: disableSnoozeAlert should have a better name. 208232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott disableSnoozeAlert(context, alarm.id); 209232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott 210232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // Disable the snooze if this alarm fires before the snoozed alarm. 211232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // This works on every alarm since the user most likely intends to 212232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // have the modified alarm fire next. 213e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott clearSnoozeIfNeeded(context, timeInMillis); 214c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott } 215c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott 2165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project setNextAlert(context); 217c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott 218c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott return timeInMillis; 2195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 2205fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 2215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 2225fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * A convenience method to enable or disable an alarm. 2235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * 2245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * @param id corresponds to the _id column 2255fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * @param enabled corresponds to the ENABLED column 2265fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 2275fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 228d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static void enableAlarm( 2295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project final Context context, final int id, boolean enabled) { 2305fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project enableAlarmInternal(context, id, enabled); 2315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project setNextAlert(context); 2325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 2335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 234d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private static void enableAlarmInternal(final Context context, 235d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott final int id, boolean enabled) { 236d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott enableAlarmInternal(context, getAlarm(context.getContentResolver(), id), 237d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott enabled); 238d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 2395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 240d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private static void enableAlarmInternal(final Context context, 241d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott final Alarm alarm, boolean enabled) { 24222924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott if (alarm == null) { 24322924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott return; 24422924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott } 245d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott ContentResolver resolver = context.getContentResolver(); 2465fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 2475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project ContentValues values = new ContentValues(2); 248d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott values.put(Alarm.Columns.ENABLED, enabled ? 1 : 0); 2495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 250d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // If we are enabling the alarm, calculate alarm time since the time 251d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // value in Alarm may be old. 2525fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project if (enabled) { 253d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott long time = 0; 254d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (!alarm.daysOfWeek.isRepeatSet()) { 255e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott time = calculateAlarm(alarm); 2565fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 257d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott values.put(Alarm.Columns.ALARM_TIME, time); 25822924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott } else { 25922924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott // Clear the snooze if the id matches. 26022924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott disableSnoozeAlert(context, alarm.id); 2615fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 2625fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 263d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott resolver.update(ContentUris.withAppendedId( 264d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm.Columns.CONTENT_URI, alarm.id), values, null, null); 2655fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 2665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 267d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static Alarm calculateNextAlert(final Context context) { 268d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm alarm = null; 269d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott long minTime = Long.MAX_VALUE; 27098948f9ce1dabcc79350a847baf220635b0c087aPatrick Scott long now = System.currentTimeMillis(); 271d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Cursor cursor = getFilteredAlarmsCursor(context.getContentResolver()); 272d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (cursor != null) { 273d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (cursor.moveToFirst()) { 274d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott do { 275d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm a = new Alarm(cursor); 276d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // A time of 0 indicates this is a repeating alarm, so 277d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // calculate the time to get the next alert. 278d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (a.time == 0) { 279e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott a.time = calculateAlarm(a); 28098948f9ce1dabcc79350a847baf220635b0c087aPatrick Scott } else if (a.time < now) { 28198948f9ce1dabcc79350a847baf220635b0c087aPatrick Scott // Expired alarm, disable it and move along. 28298948f9ce1dabcc79350a847baf220635b0c087aPatrick Scott enableAlarmInternal(context, a, false); 28398948f9ce1dabcc79350a847baf220635b0c087aPatrick Scott continue; 284d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 285d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (a.time < minTime) { 286d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott minTime = a.time; 287d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott alarm = a; 288d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 289d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } while (cursor.moveToNext()); 2905fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 291d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott cursor.close(); 2925fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 293d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott return alarm; 2945fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 2955fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 2965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 2975fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Disables non-repeating alarms that have passed. Called at 2985fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * boot. 2995fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 3005fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project public static void disableExpiredAlarms(final Context context) { 301d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Cursor cur = getFilteredAlarmsCursor(context.getContentResolver()); 3025fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project long now = System.currentTimeMillis(); 3035fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 3045fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project if (cur.moveToFirst()) { 3055fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project do { 306d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm alarm = new Alarm(cur); 307d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // A time of 0 means this alarm repeats. If the time is 308d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // non-zero, check if the time is before now. 309d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (alarm.time != 0 && alarm.time < now) { 310d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (Log.LOGV) { 311d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Log.v("** DISABLE " + alarm.id + " now " + now +" set " 312d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott + alarm.time); 313d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 314d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott enableAlarmInternal(context, alarm, false); 3155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } while (cur.moveToNext()); 3175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project cur.close(); 3195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3205fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 3215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 3225fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Called at system startup, on time/timezone change, and whenever 3235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * the user changes alarm settings. Activates snooze if set, 3245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * otherwise loads all alarms, activates next alert. 3255fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 3265fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project public static void setNextAlert(final Context context) { 327d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (!enableSnoozeAlert(context)) { 328d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm alarm = calculateNextAlert(context); 329d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (alarm != null) { 330d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott enableAlert(context, alarm, alarm.time); 3315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } else { 332d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott disableAlert(context); 3335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3345fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3355fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3365fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 3375fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 3385fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Sets alert in AlarmManger and StatusBar. This is what will 3395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * actually launch the alert when the alarm triggers. 3405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * 341d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott * @param alarm Alarm. 3425fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * @param atTimeInMillis milliseconds since epoch 3435fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 344d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private static void enableAlert(Context context, final Alarm alarm, 345d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott final long atTimeInMillis) { 3465fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project AlarmManager am = (AlarmManager) 3475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project context.getSystemService(Context.ALARM_SERVICE); 3485fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 349d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (Log.LOGV) { 350d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Log.v("** setAlert id " + alarm.id + " atTime " + atTimeInMillis); 3515d6f5fa51fa7fd13784a73199161deabec5bc898Patrick Scott } 352d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott 353d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Intent intent = new Intent(ALARM_ALERT_ACTION); 354d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott 355d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // XXX: This is a slight hack to avoid an exception in the remote 356d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // AlarmManagerService process. The AlarmManager adds extra data to 357d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // this Intent which causes it to inflate. Since the remote process 358d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // does not know about the Alarm class, it throws a 359d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // ClassNotFoundException. 360d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // 361d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // To avoid this, we marshall the data ourselves and then parcel a plain 362d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // byte[] array. The AlarmReceiver class knows to build the Alarm 363d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // object from the byte[] array. 364d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Parcel out = Parcel.obtain(); 365d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott alarm.writeToParcel(out, 0); 366d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott out.setDataPosition(0); 367d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott intent.putExtra(ALARM_RAW_DATA, out.marshall()); 368d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott 3695fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project PendingIntent sender = PendingIntent.getBroadcast( 3705fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); 3715fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 372d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott am.set(AlarmManager.RTC_WAKEUP, atTimeInMillis, sender); 3735fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 3745fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project setStatusBarIcon(context, true); 3755fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 3765fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Calendar c = Calendar.getInstance(); 377e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott c.setTimeInMillis(atTimeInMillis); 3785fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project String timeString = formatDayAndTime(context, c); 3795fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project saveNextAlarm(context, timeString); 3805fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3815fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 3825fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 3835fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Disables alert in AlarmManger and StatusBar. 3845fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * 3855fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * @param id Alarm ID. 3865fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 387d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott static void disableAlert(Context context) { 3885fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project AlarmManager am = (AlarmManager) 3895fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project context.getSystemService(Context.ALARM_SERVICE); 3905fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project PendingIntent sender = PendingIntent.getBroadcast( 391d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott context, 0, new Intent(ALARM_ALERT_ACTION), 392d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott PendingIntent.FLAG_CANCEL_CURRENT); 3935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project am.cancel(sender); 3945fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project setStatusBarIcon(context, false); 3955fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project saveNextAlarm(context, ""); 3965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3975fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 398d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott static void saveSnoozeAlert(final Context context, final int id, 399d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott final long time) { 4005fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project SharedPreferences prefs = context.getSharedPreferences( 4015fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project AlarmClock.PREFERENCES, 0); 402d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (id == -1) { 403c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott clearSnoozePreference(context, prefs); 404d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } else { 405c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott SharedPreferences.Editor ed = prefs.edit(); 406d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott ed.putInt(PREF_SNOOZE_ID, id); 407d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott ed.putLong(PREF_SNOOZE_TIME, time); 408e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott ed.commit(); 4095d6f5fa51fa7fd13784a73199161deabec5bc898Patrick Scott } 410d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // Set the next alert after updating the snooze. 411d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott setNextAlert(context); 4125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 4135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 4145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 415d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott * Disable the snooze alert if the given id matches the snooze id. 4165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 417d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott static void disableSnoozeAlert(final Context context, final int id) { 4185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project SharedPreferences prefs = context.getSharedPreferences( 4195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project AlarmClock.PREFERENCES, 0); 420d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott int snoozeId = prefs.getInt(PREF_SNOOZE_ID, -1); 421d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (snoozeId == -1) { 422d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // No snooze set, do nothing. 423d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott return; 424d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } else if (snoozeId == id) { 425d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This is the same id so clear the shared prefs. 426c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott clearSnoozePreference(context, prefs); 427d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 4285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 4295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 430e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott // Helper to remove the snooze preference. Do not use clear because that 431c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott // will erase the clock preferences. Also clear the snooze notification in 432c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott // the window shade. 433c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott private static void clearSnoozePreference(final Context context, 434c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott final SharedPreferences prefs) { 435c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott final int alarmId = prefs.getInt(PREF_SNOOZE_ID, -1); 436c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott if (alarmId != -1) { 437c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott NotificationManager nm = (NotificationManager) 438c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott context.getSystemService(Context.NOTIFICATION_SERVICE); 439c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott nm.cancel(alarmId); 440c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott } 441c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott 442c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott final SharedPreferences.Editor ed = prefs.edit(); 443e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott ed.remove(PREF_SNOOZE_ID); 444e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott ed.remove(PREF_SNOOZE_TIME); 445e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott ed.commit(); 446e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott }; 447e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott 4485fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 4495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * If there is a snooze set, enable it in AlarmManager 4505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * @return true if snooze is set 4515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 4525fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project private static boolean enableSnoozeAlert(final Context context) { 4535fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project SharedPreferences prefs = context.getSharedPreferences( 4545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project AlarmClock.PREFERENCES, 0); 4555fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 4565fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project int id = prefs.getInt(PREF_SNOOZE_ID, -1); 457d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (id == -1) { 458d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott return false; 459d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 460d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott long time = prefs.getLong(PREF_SNOOZE_TIME, -1); 461d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott 462d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // Get the alarm from the db. 463d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott final Alarm alarm = getAlarm(context.getContentResolver(), id); 46422924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott if (alarm == null) { 46522924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott return false; 46622924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott } 467d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // The time in the database is either 0 (repeating) or a specific time 468d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // for a non-repeating alarm. Update this value so the AlarmReceiver 469d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // has the right time to compare. 470d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott alarm.time = time; 471d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott 472d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott enableAlert(context, alarm, time); 4735fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return true; 4745fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 4755fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 4765fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 4775fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Tells the StatusBar whether the alarm is enabled or disabled 4785fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 4795fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project private static void setStatusBarIcon(Context context, boolean enabled) { 480fe8dd39ee5e173f15337d09c36aa453a55364e98Patrick Scott Intent alarmChanged = new Intent("android.intent.action.ALARM_CHANGED"); 4815fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project alarmChanged.putExtra("alarmSet", enabled); 4825fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project context.sendBroadcast(alarmChanged); 4835fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 4845fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 485e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott private static long calculateAlarm(Alarm alarm) { 486e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott return calculateAlarm(alarm.hour, alarm.minutes, alarm.daysOfWeek) 487e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott .getTimeInMillis(); 488e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott } 489e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 4905fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 4915fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Given an alarm in hours and minutes, return a time suitable for 4925fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * setting in AlarmManager. 4935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 494e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott static Calendar calculateAlarm(int hour, int minute, 495e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott Alarm.DaysOfWeek daysOfWeek) { 4965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 4975fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project // start with now 4985fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Calendar c = Calendar.getInstance(); 4995fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project c.setTimeInMillis(System.currentTimeMillis()); 5005fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 5015fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project int nowHour = c.get(Calendar.HOUR_OF_DAY); 5025fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project int nowMinute = c.get(Calendar.MINUTE); 5035fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 5045fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project // if alarm is behind current time, advance one day 5055fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project if (hour < nowHour || 5065fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project hour == nowHour && minute <= nowMinute) { 5075fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project c.add(Calendar.DAY_OF_YEAR, 1); 5085fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 5095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project c.set(Calendar.HOUR_OF_DAY, hour); 5105fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project c.set(Calendar.MINUTE, minute); 5115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project c.set(Calendar.SECOND, 0); 5125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project c.set(Calendar.MILLISECOND, 0); 5135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 5145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project int addDays = daysOfWeek.getNextAlarm(c); 5155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project if (addDays > 0) c.add(Calendar.DAY_OF_WEEK, addDays); 5165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return c; 5175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 5185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 5195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project static String formatTime(final Context context, int hour, int minute, 520d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm.DaysOfWeek daysOfWeek) { 5215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Calendar c = calculateAlarm(hour, minute, daysOfWeek); 5225fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return formatTime(context, c); 5235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 5245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 5255fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /* used by AlarmAlert */ 5265fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project static String formatTime(final Context context, Calendar c) { 5275fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project String format = get24HourMode(context) ? M24 : M12; 5285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return (c == null) ? "" : (String)DateFormat.format(format, c); 5295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 5305fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 5315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 5325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Shows day and time -- used for lock screen 5335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 5345fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project private static String formatDayAndTime(final Context context, Calendar c) { 5355fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project String format = get24HourMode(context) ? DM24 : DM12; 5365fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return (c == null) ? "" : (String)DateFormat.format(format, c); 5375fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 5385fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 5395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 5405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Save time of the next alarm, as a formatted string, into the system 5415fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * settings so those who care can make use of it. 5425fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 5435fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project static void saveNextAlarm(final Context context, String timeString) { 5445fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Settings.System.putString(context.getContentResolver(), 5455fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Settings.System.NEXT_ALARM_FORMATTED, 5465fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project timeString); 5475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 5485fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 5495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 5505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * @return true if clock is set to 24-hour mode 5515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 5525fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project static boolean get24HourMode(final Context context) { 5535fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return android.text.format.DateFormat.is24HourFormat(context); 5545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 5555fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project} 556