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.ContentUris; 245c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.content.ContentValues; 255fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Context; 265c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Chengimport android.content.CursorLoader; 275fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.Intent; 285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.content.SharedPreferences; 295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.database.Cursor; 305fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.net.Uri; 31d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scottimport android.os.Parcel; 325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.provider.Settings; 335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport android.text.format.DateFormat; 345fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 355fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectimport java.util.Calendar; 368304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrookimport java.util.HashSet; 378304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrookimport java.util.Set; 385fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project/** 405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * The Alarms provider supplies info about Alarm Clock settings 415fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 425fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Projectpublic class Alarms { 435fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 445c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng static final String PREFERENCES = "AlarmClock"; 455c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 46d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This action triggers the AlarmReceiver as well as the AlarmKlaxon. It 47d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // is a public action used in the manifest for receiving Alarm broadcasts 48d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // from the alarm manager. 49fa954248b41b567dfa2ddd7bd063d3936a51758eDaniel Sandler public static final String ALARM_ALERT_ACTION = "com.android.deskclock.ALARM_ALERT"; 505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 51a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram // A public action sent by AlarmKlaxon when the alarm has stopped sounding 52a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram // for any reason (e.g. because it has been dismissed from AlarmAlertFullScreen, 53a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram // or killed due to an incoming phone call, etc). 54a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram public static final String ALARM_DONE_ACTION = "com.android.deskclock.ALARM_DONE"; 55a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram 56a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram // AlarmAlertFullScreen listens for this broadcast intent, so that other applications 57a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram // can snooze the alarm (after ALARM_ALERT_ACTION and before ALARM_DONE_ACTION). 58a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram public static final String ALARM_SNOOZE_ACTION = "com.android.deskclock.ALARM_SNOOZE"; 59a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram 60a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram // AlarmAlertFullScreen listens for this broadcast intent, so that other applications 61a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram // can dismiss the alarm (after ALARM_ALERT_ACTION and before ALARM_DONE_ACTION). 62a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram public static final String ALARM_DISMISS_ACTION = "com.android.deskclock.ALARM_DISMISS"; 63a3aba0c93c31e89045cca669418e85acfb4e22fbDavid Ingram 649e33fe399ce41766dc0a2d6e8f3e2fef0d30f6c1Robyn Coultas // A public action sent by AlarmAlertFullScreen when a snoozed alarm was dismissed due 659e33fe399ce41766dc0a2d6e8f3e2fef0d30f6c1Robyn Coultas // to it handling ALARM_DISMISS_ACTION cancelled 669e33fe399ce41766dc0a2d6e8f3e2fef0d30f6c1Robyn Coultas public static final String ALARM_SNOOZE_CANCELLED = "com.android.deskclock.ALARM_SNOOZE_CANCELLED"; 679e33fe399ce41766dc0a2d6e8f3e2fef0d30f6c1Robyn Coultas 685c464d35f230912053d7a5873dd6b59ca6e11852Isaac Katzenelson // A broadcast sent every time the next alarm time is set in the system 695c464d35f230912053d7a5873dd6b59ca6e11852Isaac Katzenelson public static final String NEXT_ALARM_TIME_SET = "com.android.deskclock.NEXT_ALARM_TIME_SET"; 705c464d35f230912053d7a5873dd6b59ca6e11852Isaac Katzenelson 71d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This is a private action used by the AlarmKlaxon to update the UI to 72d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // show the alarm has been killed. 73d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String ALARM_KILLED = "alarm_killed"; 745fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 75d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // Extra in the ALARM_KILLED intent to indicate to the user how long the 76d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // alarm played before being killed. 77d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String ALARM_KILLED_TIMEOUT = "alarm_killed_timeout"; 785fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 79be452965e9b8467d2f640ccee1002119bb7d2761Robyn Coultas // Extra in the ALARM_KILLED intent to indicate when alarm was replaced 80be452965e9b8467d2f640ccee1002119bb7d2761Robyn Coultas public static final String ALARM_REPLACED = "alarm_replaced"; 81be452965e9b8467d2f640ccee1002119bb7d2761Robyn Coultas 82d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This string is used to indicate a silent alarm in the db. 83d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String ALARM_ALERT_SILENT = "silent"; 845fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 85d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This intent is sent from the notification when the user cancels the 86d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // snooze alert. 87d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String CANCEL_SNOOZE = "cancel_snooze"; 885fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 89d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This string is used when passing an Alarm object through an intent. 90d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String ALARM_INTENT_EXTRA = "intent.extra.alarm"; 915fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 92d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This extra is the raw Alarm object data. It is used in the 93d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // AlarmManagerService to avoid a ClassNotFoundException when filling in 94d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // the Intent extras. 95d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static final String ALARM_RAW_DATA = "intent.extra.alarm_raw"; 965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 978304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook private static final String PREF_SNOOZE_IDS = "snooze_ids"; 988304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook private static final String PREF_SNOOZE_TIME = "snooze_time"; 995fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 100d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private final static String DM12 = "E h:mm aa"; 101bababb66c17c665d374313da47e2f3734adec83aPatrick Scott private final static String DM24 = "E kk:mm"; 1025fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 103d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private final static String M12 = "h:mm aa"; 1041ebd23eaa82ab560f5c7d8aeca8df7512df8424ePatrick Scott // Shared with DigitalClock 1051ebd23eaa82ab560f5c7d8aeca8df7512df8424ePatrick Scott final static String M24 = "kk:mm"; 1065fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 1078304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final static int INVALID_ALARM_ID = -1; 1088304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 1095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 1106064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott * Creates a new Alarm and fills in the given alarm's id. 1115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 112e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott public static long addAlarm(Context context, Alarm alarm) { 113e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott ContentValues values = createContentValues(alarm); 1146064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott Uri uri = context.getContentResolver().insert( 1156064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott Alarm.Columns.CONTENT_URI, values); 1166064d3f7aabcb073dc3f917e049bc04c67fb6b29Patrick Scott alarm.id = (int) ContentUris.parseId(uri); 117e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 118e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott long timeInMillis = calculateAlarm(alarm); 119e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott if (alarm.enabled) { 120e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott clearSnoozeIfNeeded(context, timeInMillis); 121e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott } 122e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott setNextAlert(context); 123e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott return timeInMillis; 1245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 1255fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 1265fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 1275fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Removes an existing Alarm. If this alarm is snoozing, disables 1285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * snooze. Sets next alert. 1295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 130bb13b216f986fc75dbd82d38f2bd6b2fbeb08abdPatrick Scott public static void deleteAlarm(Context context, int alarmId) { 1318304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook if (alarmId == INVALID_ALARM_ID) return; 1325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 1335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project ContentResolver contentResolver = context.getContentResolver(); 1345fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /* If alarm is snoozing, lose it */ 135d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott disableSnoozeAlert(context, alarmId); 1365fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 137d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Uri uri = ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarmId); 138d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott contentResolver.delete(uri, "", null); 1395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 1405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project setNextAlert(context); 1415fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 1425fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 1435c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1445c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng public static CursorLoader getAlarmsCursorLoader(Context context) { 1455c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng return new CursorLoader(context, Alarm.Columns.CONTENT_URI, 1465c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng Alarm.Columns.ALARM_QUERY_COLUMNS, null, null, Alarm.Columns.DEFAULT_SORT_ORDER); 1475c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 1485c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng 1495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 1505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Queries all alarms 1515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * @return cursor over all alarms 1525fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 153d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static Cursor getAlarmsCursor(ContentResolver contentResolver) { 1545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return contentResolver.query( 155d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm.Columns.CONTENT_URI, Alarm.Columns.ALARM_QUERY_COLUMNS, 156d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott null, null, Alarm.Columns.DEFAULT_SORT_ORDER); 1575fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 1585fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 159d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // Private method to get a more limited set of alarms from the database. 160d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private static Cursor getFilteredAlarmsCursor( 161d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott ContentResolver contentResolver) { 162d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott return contentResolver.query(Alarm.Columns.CONTENT_URI, 163d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm.Columns.ALARM_QUERY_COLUMNS, Alarm.Columns.WHERE_ENABLED, 164d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott null, null); 1655fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 1665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 167e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott private static ContentValues createContentValues(Alarm alarm) { 168e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott ContentValues values = new ContentValues(8); 169e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott // Set the alarm_time value if this alarm does not repeat. This will be 170e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott // used later to disable expire alarms. 171e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott long time = 0; 172e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott if (!alarm.daysOfWeek.isRepeatSet()) { 173e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott time = calculateAlarm(alarm); 174e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott } 175e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 1760cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng // -1 means generate new id. 1770cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng if (alarm.id != -1) { 1780cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng values.put(Alarm.Columns._ID, alarm.id); 1790cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng } 1800cb70993e26f300f92423bfced0d8cb3efc3f304Chiao Cheng 181e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.ENABLED, alarm.enabled ? 1 : 0); 182e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.HOUR, alarm.hour); 183e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.MINUTES, alarm.minutes); 184501a153616bd44880b587447788990d83f433a8fPatrick Scott values.put(Alarm.Columns.ALARM_TIME, time); 185e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.DAYS_OF_WEEK, alarm.daysOfWeek.getCoded()); 186e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.VIBRATE, alarm.vibrate); 187e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.MESSAGE, alarm.label); 188e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 189e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott // A null alert Uri indicates a silent alarm. 190e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values.put(Alarm.Columns.ALERT, alarm.alert == null ? ALARM_ALERT_SILENT 191e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott : alarm.alert.toString()); 192e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 193e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott return values; 194e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott } 195e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 196e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott private static void clearSnoozeIfNeeded(Context context, long alarmTime) { 197e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott // If this alarm fires before the next snooze, clear the snooze to 198e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott // enable this alarm. 1995c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng SharedPreferences prefs = context.getSharedPreferences(PREFERENCES, 0); 2008304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 2018304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook // Get the list of snoozed alarms 2028304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final Set<String> snoozedIds = prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>()); 2038304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook for (String snoozedAlarm : snoozedIds) { 2048304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final long snoozeTime = prefs.getLong(getAlarmPrefSnoozeTimeKey(snoozedAlarm), 0); 2058304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook if (alarmTime < snoozeTime) { 2068304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final int alarmId = Integer.parseInt(snoozedAlarm); 2078304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook clearSnoozePreference(context, prefs, alarmId); 2088304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 209e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott } 210e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott } 211e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 2125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 213d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott * Return an Alarm object representing the alarm id in the database. 214d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott * Returns null if no alarm exists. 2155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 216d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static Alarm getAlarm(ContentResolver contentResolver, int alarmId) { 2175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Cursor cursor = contentResolver.query( 218d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarmId), 219d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm.Columns.ALARM_QUERY_COLUMNS, 220d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott null, null, null); 221d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm alarm = null; 222d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (cursor != null) { 223d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (cursor.moveToFirst()) { 224d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott alarm = new Alarm(cursor); 225d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 226d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott cursor.close(); 227d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 228d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott return alarm; 2295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 2305fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 2315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 2325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 2335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * A convenience method to set an alarm in the Alarms 2345fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * content provider. 2355c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * @return Time when the alarm will fire. Or < 1 if update failed. 2365fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 237e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott public static long setAlarm(Context context, Alarm alarm) { 238e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott ContentValues values = createContentValues(alarm); 2395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project ContentResolver resolver = context.getContentResolver(); 2405c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng long rowsUpdated = resolver.update( 241e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarm.id), 242e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott values, null, null); 2435c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng if (rowsUpdated < 1) { 2445c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng Log.e("Error updating alarm " + alarm); 2455c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng return rowsUpdated; 2465c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng } 2475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 248e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott long timeInMillis = calculateAlarm(alarm); 249c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott 250e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott if (alarm.enabled) { 251232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // Disable the snooze if we just changed the snoozed alarm. This 252232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // only does work if the snoozed alarm is the same as the given 253232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // alarm. 254232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // TODO: disableSnoozeAlert should have a better name. 255232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott disableSnoozeAlert(context, alarm.id); 256232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott 257232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // Disable the snooze if this alarm fires before the snoozed alarm. 258232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // This works on every alarm since the user most likely intends to 259232725e8c1b1b85a44857cedcc842dcd2c956dc2Patrick Scott // have the modified alarm fire next. 260e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott clearSnoozeIfNeeded(context, timeInMillis); 261c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott } 262c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott 2635fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project setNextAlert(context); 264c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott 265c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott return timeInMillis; 2665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 2675fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 2685fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 2695fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * A convenience method to enable or disable an alarm. 2705fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * 2715fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * @param id corresponds to the _id column 2725fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * @param enabled corresponds to the ENABLED column 2735fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 2745fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 275d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott public static void enableAlarm( 2765fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project final Context context, final int id, boolean enabled) { 2775fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project enableAlarmInternal(context, id, enabled); 2785fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project setNextAlert(context); 2795fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 2805fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 281d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private static void enableAlarmInternal(final Context context, 282d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott final int id, boolean enabled) { 283d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott enableAlarmInternal(context, getAlarm(context.getContentResolver(), id), 284d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott enabled); 285d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 2865fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 287d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private static void enableAlarmInternal(final Context context, 288d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott final Alarm alarm, boolean enabled) { 28922924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott if (alarm == null) { 29022924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott return; 29122924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott } 292d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott ContentResolver resolver = context.getContentResolver(); 2935fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 2945fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project ContentValues values = new ContentValues(2); 295d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott values.put(Alarm.Columns.ENABLED, enabled ? 1 : 0); 2965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 297d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // If we are enabling the alarm, calculate alarm time since the time 298d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // value in Alarm may be old. 2995fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project if (enabled) { 300d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott long time = 0; 301d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (!alarm.daysOfWeek.isRepeatSet()) { 302e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott time = calculateAlarm(alarm); 3035fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 304d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott values.put(Alarm.Columns.ALARM_TIME, time); 30522924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott } else { 30622924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott // Clear the snooze if the id matches. 30722924b6afee333e16fb62a19f1ac044c87c528b5Patrick Scott disableSnoozeAlert(context, alarm.id); 3085fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 310d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott resolver.update(ContentUris.withAppendedId( 311d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm.Columns.CONTENT_URI, alarm.id), values, null, null); 3125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 3148304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook private static Alarm calculateNextAlert(final Context context) { 315d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott long minTime = Long.MAX_VALUE; 31698948f9ce1dabcc79350a847baf220635b0c087aPatrick Scott long now = System.currentTimeMillis(); 3175c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng final SharedPreferences prefs = context.getSharedPreferences(PREFERENCES, 0); 3188304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 3198304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook Set<Alarm> alarms = new HashSet<Alarm>(); 3208304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 3218304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook // We need to to build the list of alarms from both the snoozed list and the scheduled 3228304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook // list. For a non-repeating alarm, when it goes of, it becomes disabled. A snoozed 3238304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook // non-repeating alarm is not in the active list in the database. 3248304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 3258304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook // first go through the snoozed alarms 3268304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final Set<String> snoozedIds = prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>()); 3278304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook for (String snoozedAlarm : snoozedIds) { 3288304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final int alarmId = Integer.parseInt(snoozedAlarm); 3298304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final Alarm a = getAlarm(context.getContentResolver(), alarmId); 3308304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook alarms.add(a); 3318304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 3328304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 3338304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook // Now add the scheduled alarms 3348304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final Cursor cursor = getFilteredAlarmsCursor(context.getContentResolver()); 335d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott if (cursor != null) { 33699ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden try { 33799ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden if (cursor.moveToFirst()) { 3388304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook do { 3398304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final Alarm a = new Alarm(cursor); 3408304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook alarms.add(a); 3418304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } while (cursor.moveToNext()); 3428304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 34399ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden } finally { 34499ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden cursor.close(); 3455fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3465fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3478304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 3488304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook Alarm alarm = null; 3498304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 3508304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook for (Alarm a : alarms) { 3518304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook // A time of 0 indicates this is a repeating alarm, so 3528304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook // calculate the time to get the next alert. 3538304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook if (a.time == 0) { 3548304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook a.time = calculateAlarm(a); 3558304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 3568304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 3578304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook // Update the alarm if it has been snoozed 3588304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook updateAlarmTimeForSnooze(prefs, a); 3598304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 3608304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook if (a.time < now) { 3618304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook Log.v("Disabling expired alarm set for " + Log.formatTime(a.time)); 3628304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook // Expired alarm, disable it and move along. 3638304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook enableAlarmInternal(context, a, false); 3648304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook continue; 3658304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 3668304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook if (a.time < minTime) { 3678304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook minTime = a.time; 3688304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook alarm = a; 3698304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 3708304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 3718304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 372d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott return alarm; 3735fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3745fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 3755fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 3765fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Disables non-repeating alarms that have passed. Called at 3775fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * boot. 3785fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 3795fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project public static void disableExpiredAlarms(final Context context) { 380d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Cursor cur = getFilteredAlarmsCursor(context.getContentResolver()); 3815fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project long now = System.currentTimeMillis(); 3825fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 38399ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden try { 38499ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden if (cur.moveToFirst()) { 38599ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden do { 38699ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden Alarm alarm = new Alarm(cur); 38799ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden // A time of 0 means this alarm repeats. If the time is 38899ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden // non-zero, check if the time is before now. 38999ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden if (alarm.time != 0 && alarm.time < now) { 39099ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden Log.v("Disabling expired alarm set for " + 39199ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden Log.formatTime(alarm.time)); 39299ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden enableAlarmInternal(context, alarm, false); 39399ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden } 39499ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden } while (cur.moveToNext()); 39599ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden } 39699ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden } finally { 39799ae7660f1e5e4645c889e78e26d44de20a7caf3Andy McFadden cur.close(); 3985fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 3995fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 4005fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 4015fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 4025fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Called at system startup, on time/timezone change, and whenever 4035fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * the user changes alarm settings. Activates snooze if set, 4045fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * otherwise loads all alarms, activates next alert. 4055fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 4065fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project public static void setNextAlert(final Context context) { 4078304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final Alarm alarm = calculateNextAlert(context); 4088304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook if (alarm != null) { 4098304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook enableAlert(context, alarm, alarm.time); 4108304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } else { 4118304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook disableAlert(context); 4125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 4135c464d35f230912053d7a5873dd6b59ca6e11852Isaac Katzenelson Intent i = new Intent(NEXT_ALARM_TIME_SET); 4145c464d35f230912053d7a5873dd6b59ca6e11852Isaac Katzenelson context.sendBroadcast(i); 4155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 4165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 4175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 4185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Sets alert in AlarmManger and StatusBar. This is what will 4195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * actually launch the alert when the alarm triggers. 4205fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * 421d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott * @param alarm Alarm. 4225fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * @param atTimeInMillis milliseconds since epoch 4235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 424d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott private static void enableAlert(Context context, final Alarm alarm, 425d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott final long atTimeInMillis) { 4265fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project AlarmManager am = (AlarmManager) 4275fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project context.getSystemService(Context.ALARM_SERVICE); 4285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 4291e34a1bead76f4c3fa6e2baec327e5846f4c23fdRobyn Coultas // Intentionally verbose: always log the alarm time to provide useful 4301e34a1bead76f4c3fa6e2baec327e5846f4c23fdRobyn Coultas // information in bug reports. 4311e34a1bead76f4c3fa6e2baec327e5846f4c23fdRobyn Coultas Log.v("Alarm set for id=" + alarm.id + " " + Log.formatTime(atTimeInMillis)); 432d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott 433d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Intent intent = new Intent(ALARM_ALERT_ACTION); 434d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott 435d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // XXX: This is a slight hack to avoid an exception in the remote 436d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // AlarmManagerService process. The AlarmManager adds extra data to 437d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // this Intent which causes it to inflate. Since the remote process 438d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // does not know about the Alarm class, it throws a 439d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // ClassNotFoundException. 440d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // 441d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // To avoid this, we marshall the data ourselves and then parcel a plain 442d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // byte[] array. The AlarmReceiver class knows to build the Alarm 443d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // object from the byte[] array. 444d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Parcel out = Parcel.obtain(); 445d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott alarm.writeToParcel(out, 0); 446d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott out.setDataPosition(0); 447d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott intent.putExtra(ALARM_RAW_DATA, out.marshall()); 448d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott 4495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project PendingIntent sender = PendingIntent.getBroadcast( 4505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); 4515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 452d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott am.set(AlarmManager.RTC_WAKEUP, atTimeInMillis, sender); 4535fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 4545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project setStatusBarIcon(context, true); 4555fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 4565fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Calendar c = Calendar.getInstance(); 457e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott c.setTimeInMillis(atTimeInMillis); 4585fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project String timeString = formatDayAndTime(context, c); 4595fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project saveNextAlarm(context, timeString); 4605fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 4615fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 4625fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 4639e33fe399ce41766dc0a2d6e8f3e2fef0d30f6c1Robyn Coultas * Disables alert in AlarmManager and StatusBar. 4645fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * 4655c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng * @param context The context 4665fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 467d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott static void disableAlert(Context context) { 4685fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project AlarmManager am = (AlarmManager) 4695fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project context.getSystemService(Context.ALARM_SERVICE); 4705fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project PendingIntent sender = PendingIntent.getBroadcast( 471d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott context, 0, new Intent(ALARM_ALERT_ACTION), 472d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott PendingIntent.FLAG_CANCEL_CURRENT); 4735fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project am.cancel(sender); 4745fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project setStatusBarIcon(context, false); 4751e34a1bead76f4c3fa6e2baec327e5846f4c23fdRobyn Coultas // Intentionally verbose: always log the lack of a next alarm to provide useful 4761e34a1bead76f4c3fa6e2baec327e5846f4c23fdRobyn Coultas // information in bug reports. 4771e34a1bead76f4c3fa6e2baec327e5846f4c23fdRobyn Coultas Log.v("No next alarm"); 4785fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project saveNextAlarm(context, ""); 4795fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 4805fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 481d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott static void saveSnoozeAlert(final Context context, final int id, 482d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott final long time) { 4835c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng SharedPreferences prefs = context.getSharedPreferences(PREFERENCES, 0); 4848304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook if (id == INVALID_ALARM_ID) { 4858304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook clearAllSnoozePreferences(context, prefs); 486d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } else { 4878304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final Set<String> snoozedIds = 4888304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>()); 4898304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook snoozedIds.add(Integer.toString(id)); 4908304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final SharedPreferences.Editor ed = prefs.edit(); 4918304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook ed.putStringSet(PREF_SNOOZE_IDS, snoozedIds); 4928304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook ed.putLong(getAlarmPrefSnoozeTimeKey(id), time); 493c6098ef1fc69fe117343cc2e3db0d2b97b2daa6fBrad Fitzpatrick ed.apply(); 4945d6f5fa51fa7fd13784a73199161deabec5bc898Patrick Scott } 495d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // Set the next alert after updating the snooze. 496d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott setNextAlert(context); 4975fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 4985fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 4998304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook private static String getAlarmPrefSnoozeTimeKey(int id) { 5008304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook return getAlarmPrefSnoozeTimeKey(Integer.toString(id)); 5018304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 5028304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 5038304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook private static String getAlarmPrefSnoozeTimeKey(String id) { 5048304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook return PREF_SNOOZE_TIME + id; 5058304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 5068304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 5075fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 508d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott * Disable the snooze alert if the given id matches the snooze id. 5095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 510d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott static void disableSnoozeAlert(final Context context, final int id) { 5115c3795c271bc6160f0ae2056627e9e96ffdc335cChiao Cheng SharedPreferences prefs = context.getSharedPreferences(PREFERENCES, 0); 5128304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook if (hasAlarmBeenSnoozed(prefs, id)) { 513d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // This is the same id so clear the shared prefs. 5148304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook clearSnoozePreference(context, prefs, id); 515d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 5165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 5175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 518e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott // Helper to remove the snooze preference. Do not use clear because that 519c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott // will erase the clock preferences. Also clear the snooze notification in 520c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott // the window shade. 521c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott private static void clearSnoozePreference(final Context context, 5228304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final SharedPreferences prefs, final int id) { 5238304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final String alarmStr = Integer.toString(id); 5248304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final Set<String> snoozedIds = 5258304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>()); 5268304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook if (snoozedIds.contains(alarmStr)) { 527c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott NotificationManager nm = (NotificationManager) 528c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott context.getSystemService(Context.NOTIFICATION_SERVICE); 5298304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook nm.cancel(id); 530c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott } 531c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott 532c7edd6ea840e25cb04d090b6c29dc96c04d2be40Patrick Scott final SharedPreferences.Editor ed = prefs.edit(); 5338304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook snoozedIds.remove(alarmStr); 5348304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook ed.putStringSet(PREF_SNOOZE_IDS, snoozedIds); 5358304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook ed.remove(getAlarmPrefSnoozeTimeKey(alarmStr)); 5368304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook ed.apply(); 5378304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 5388304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 5398304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook private static void clearAllSnoozePreferences(final Context context, 5408304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final SharedPreferences prefs) { 5418304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook NotificationManager nm = (NotificationManager) 5428304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook context.getSystemService(Context.NOTIFICATION_SERVICE); 5438304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final Set<String> snoozedIds = 5448304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>()); 5458304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final SharedPreferences.Editor ed = prefs.edit(); 5468304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook for (String snoozeId : snoozedIds) { 5478304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook nm.cancel(Integer.parseInt(snoozeId)); 5488304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook ed.remove(getAlarmPrefSnoozeTimeKey(snoozeId)); 5498304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 5508304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 5518304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook ed.remove(PREF_SNOOZE_IDS); 552c6098ef1fc69fe117343cc2e3db0d2b97b2daa6fBrad Fitzpatrick ed.apply(); 5538304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 5548304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 5558304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook private static boolean hasAlarmBeenSnoozed(final SharedPreferences prefs, final int alarmId) { 5568304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final Set<String> snoozedIds = prefs.getStringSet(PREF_SNOOZE_IDS, null); 5578304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook 5588304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook // Return true if there a valid snoozed alarmId was saved 5598304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook return snoozedIds != null && snoozedIds.contains(Integer.toString(alarmId)); 5608304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook } 561e77fa5af5ac139f69ad504dbadd6f6aaab8c064dPatrick Scott 5625fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 5638304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook * Updates the specified Alarm with the additional snooze time. 5648304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook * Returns a boolean indicating whether the alarm was updated. 5655fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 5668304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook private static boolean updateAlarmTimeForSnooze( 5678304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final SharedPreferences prefs, final Alarm alarm) { 5688304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook if (!hasAlarmBeenSnoozed(prefs, alarm.id)) { 5698304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook // No need to modify the alarm 570d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott return false; 571d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott } 572d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott 5738304c6e63ee1ff86208bac6f79285905027e95e8Paul Westbrook final long time = prefs.getLong(getAlarmPrefSnoozeTimeKey(alarm.id), -1); 574d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // The time in the database is either 0 (repeating) or a specific time 575d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // for a non-repeating alarm. Update this value so the AlarmReceiver 576d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott // has the right time to compare. 577d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott alarm.time = time; 578d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott 5795fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return true; 5805fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 5815fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 5825fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 5835fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Tells the StatusBar whether the alarm is enabled or disabled 5845fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 5855fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project private static void setStatusBarIcon(Context context, boolean enabled) { 586fe8dd39ee5e173f15337d09c36aa453a55364e98Patrick Scott Intent alarmChanged = new Intent("android.intent.action.ALARM_CHANGED"); 5875fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project alarmChanged.putExtra("alarmSet", enabled); 5885fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project context.sendBroadcast(alarmChanged); 5895fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 5905fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 591e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott private static long calculateAlarm(Alarm alarm) { 592e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott return calculateAlarm(alarm.hour, alarm.minutes, alarm.daysOfWeek) 593e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott .getTimeInMillis(); 594e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott } 595e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott 5965fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 5975fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Given an alarm in hours and minutes, return a time suitable for 5985fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * setting in AlarmManager. 5995fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 600e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott static Calendar calculateAlarm(int hour, int minute, 601e46be904bd76dff5a13aeef12e9bfeddac7bbe81Patrick Scott Alarm.DaysOfWeek daysOfWeek) { 6025fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 6035fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project // start with now 6045fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Calendar c = Calendar.getInstance(); 6055fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project c.setTimeInMillis(System.currentTimeMillis()); 6065fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 6075fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project int nowHour = c.get(Calendar.HOUR_OF_DAY); 6085fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project int nowMinute = c.get(Calendar.MINUTE); 6095fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 6105fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project // if alarm is behind current time, advance one day 6115fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project if (hour < nowHour || 6125fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project hour == nowHour && minute <= nowMinute) { 6135fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project c.add(Calendar.DAY_OF_YEAR, 1); 6145fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 6155fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project c.set(Calendar.HOUR_OF_DAY, hour); 6165fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project c.set(Calendar.MINUTE, minute); 6175fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project c.set(Calendar.SECOND, 0); 6185fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project c.set(Calendar.MILLISECOND, 0); 6195fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 6205fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project int addDays = daysOfWeek.getNextAlarm(c); 6215fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project if (addDays > 0) c.add(Calendar.DAY_OF_WEEK, addDays); 6225fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return c; 6235fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 6245fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 6255fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project static String formatTime(final Context context, int hour, int minute, 626d776e51cec79901a0d656bba7b1f3780cceac57dPatrick Scott Alarm.DaysOfWeek daysOfWeek) { 6275fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Calendar c = calculateAlarm(hour, minute, daysOfWeek); 6285fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return formatTime(context, c); 6295fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 6305fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 6315fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /* used by AlarmAlert */ 6325fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project static String formatTime(final Context context, Calendar c) { 6335fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project String format = get24HourMode(context) ? M24 : M12; 6345fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return (c == null) ? "" : (String)DateFormat.format(format, c); 6355fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 6365fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 6375fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 6385fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Shows day and time -- used for lock screen 6395fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 6405fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project private static String formatDayAndTime(final Context context, Calendar c) { 6415fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project String format = get24HourMode(context) ? DM24 : DM12; 6425fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return (c == null) ? "" : (String)DateFormat.format(format, c); 6435fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 6445fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 6455fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 6465fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * Save time of the next alarm, as a formatted string, into the system 6475fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * settings so those who care can make use of it. 6485fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 6495fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project static void saveNextAlarm(final Context context, String timeString) { 6505fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Settings.System.putString(context.getContentResolver(), 6515fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project Settings.System.NEXT_ALARM_FORMATTED, 6525fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project timeString); 6535fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 6545fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project 6555fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project /** 6565fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project * @return true if clock is set to 24-hour mode 6575fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project */ 658421751e187dfa61bc1e48b52cdaf366628b06dd4Isaac Katzenelson public static boolean get24HourMode(final Context context) { 6595fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project return android.text.format.DateFormat.is24HourFormat(context); 6605fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project } 6615fedae0fb8cc29db88719329d52bdd62aad14277The Android Open Source Project} 662