| /* |
| * Copyright (C) 2007 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.android.deskclock; |
| |
| import android.app.AlarmManager; |
| import android.app.NotificationManager; |
| import android.app.PendingIntent; |
| import android.content.ContentResolver; |
| import android.content.ContentUris; |
| import android.content.ContentValues; |
| import android.content.Context; |
| import android.content.CursorLoader; |
| import android.content.Intent; |
| import android.content.SharedPreferences; |
| import android.database.Cursor; |
| import android.net.Uri; |
| import android.os.Parcel; |
| import android.provider.Settings; |
| import android.text.TextUtils; |
| import android.text.format.DateFormat; |
| |
| import java.util.Calendar; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| /** |
| * The Alarms provider supplies info about Alarm Clock settings |
| */ |
| public class Alarms { |
| |
| static final String PREFERENCES = "AlarmClock"; |
| |
| // This action triggers the AlarmReceiver as well as the AlarmKlaxon. It |
| // is a public action used in the manifest for receiving Alarm broadcasts |
| // from the alarm manager. |
| public static final String ALARM_ALERT_ACTION = "com.android.deskclock.ALARM_ALERT"; |
| |
| // A public action sent by AlarmKlaxon when the alarm has stopped sounding |
| // for any reason (e.g. because it has been dismissed from AlarmAlertFullScreen, |
| // or killed due to an incoming phone call, etc). |
| public static final String ALARM_DONE_ACTION = "com.android.deskclock.ALARM_DONE"; |
| |
| // AlarmAlertFullScreen listens for this broadcast intent, so that other applications |
| // can snooze the alarm (after ALARM_ALERT_ACTION and before ALARM_DONE_ACTION). |
| public static final String ALARM_SNOOZE_ACTION = "com.android.deskclock.ALARM_SNOOZE"; |
| |
| // AlarmAlertFullScreen listens for this broadcast intent, so that other applications |
| // can dismiss the alarm (after ALARM_ALERT_ACTION and before ALARM_DONE_ACTION). |
| public static final String ALARM_DISMISS_ACTION = "com.android.deskclock.ALARM_DISMISS"; |
| |
| // A public action sent by AlarmAlertFullScreen when a snoozed alarm was dismissed due |
| // to it handling ALARM_DISMISS_ACTION cancelled |
| public static final String ALARM_SNOOZE_CANCELLED = "com.android.deskclock.ALARM_SNOOZE_CANCELLED"; |
| |
| // A broadcast sent every time the next alarm time is set in the system |
| public static final String NEXT_ALARM_TIME_SET = "com.android.deskclock.NEXT_ALARM_TIME_SET"; |
| |
| // This is a private action used by the AlarmKlaxon to update the UI to |
| // show the alarm has been killed. |
| public static final String ALARM_KILLED = "alarm_killed"; |
| |
| // Extra in the ALARM_KILLED intent to indicate to the user how long the |
| // alarm played before being killed. |
| public static final String ALARM_KILLED_TIMEOUT = "alarm_killed_timeout"; |
| |
| // Extra in the ALARM_KILLED intent to indicate when alarm was replaced |
| public static final String ALARM_REPLACED = "alarm_replaced"; |
| |
| // This string is used to indicate a silent alarm in the db. |
| public static final String ALARM_ALERT_SILENT = "silent"; |
| |
| // This intent is sent from the notification when the user cancels the |
| // snooze alert. |
| public static final String CANCEL_SNOOZE = "cancel_snooze"; |
| |
| // This string is used when passing an Alarm object through an intent. |
| public static final String ALARM_INTENT_EXTRA = "intent.extra.alarm"; |
| |
| // This extra is the raw Alarm object data. It is used in the |
| // AlarmManagerService to avoid a ClassNotFoundException when filling in |
| // the Intent extras. |
| public static final String ALARM_RAW_DATA = "intent.extra.alarm_raw"; |
| |
| private static final String PREF_SNOOZE_IDS = "snooze_ids"; |
| private static final String PREF_SNOOZE_TIME = "snooze_time"; |
| |
| private final static String DM12 = "E h:mm aa"; |
| private final static String DM24 = "E kk:mm"; |
| |
| private final static String M12 = "h:mm aa"; |
| // Shared with DigitalClock |
| final static String M24 = "kk:mm"; |
| |
| final static int INVALID_ALARM_ID = -1; |
| |
| /** |
| * Creates a new Alarm and fills in the given alarm's id. |
| */ |
| public static long addAlarm(Context context, Alarm alarm) { |
| ContentValues values = createContentValues(alarm); |
| Uri uri = context.getContentResolver().insert( |
| Alarm.Columns.CONTENT_URI, values); |
| alarm.id = (int) ContentUris.parseId(uri); |
| |
| long timeInMillis = calculateAlarm(alarm); |
| if (alarm.enabled) { |
| clearSnoozeIfNeeded(context, timeInMillis); |
| } |
| setNextAlert(context); |
| return timeInMillis; |
| } |
| |
| /** |
| * Removes an existing Alarm. If this alarm is snoozing, disables |
| * snooze. Sets next alert. |
| */ |
| public static void deleteAlarm(Context context, int alarmId) { |
| if (alarmId == INVALID_ALARM_ID) return; |
| |
| ContentResolver contentResolver = context.getContentResolver(); |
| /* If alarm is snoozing, lose it */ |
| disableSnoozeAlert(context, alarmId); |
| |
| Uri uri = ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarmId); |
| contentResolver.delete(uri, "", null); |
| |
| setNextAlert(context); |
| } |
| |
| |
| public static CursorLoader getAlarmsCursorLoader(Context context) { |
| return new CursorLoader(context, Alarm.Columns.CONTENT_URI, |
| Alarm.Columns.ALARM_QUERY_COLUMNS, null, null, Alarm.Columns.DEFAULT_SORT_ORDER); |
| } |
| |
| /** |
| * Queries all alarms |
| * @return cursor over all alarms |
| */ |
| public static Cursor getAlarmsCursor(ContentResolver contentResolver) { |
| return contentResolver.query( |
| Alarm.Columns.CONTENT_URI, Alarm.Columns.ALARM_QUERY_COLUMNS, |
| null, null, Alarm.Columns.DEFAULT_SORT_ORDER); |
| } |
| |
| // Private method to get a more limited set of alarms from the database. |
| private static Cursor getFilteredAlarmsCursor( |
| ContentResolver contentResolver) { |
| return contentResolver.query(Alarm.Columns.CONTENT_URI, |
| Alarm.Columns.ALARM_QUERY_COLUMNS, Alarm.Columns.WHERE_ENABLED, |
| null, null); |
| } |
| |
| private static ContentValues createContentValues(Alarm alarm) { |
| ContentValues values = new ContentValues(8); |
| // Set the alarm_time value if this alarm does not repeat. This will be |
| // used later to disable expire alarms. |
| long time = 0; |
| if (!alarm.daysOfWeek.isRepeatSet()) { |
| time = calculateAlarm(alarm); |
| } |
| |
| // -1 means generate new id. |
| if (alarm.id != -1) { |
| values.put(Alarm.Columns._ID, alarm.id); |
| } |
| |
| values.put(Alarm.Columns.ENABLED, alarm.enabled ? 1 : 0); |
| values.put(Alarm.Columns.HOUR, alarm.hour); |
| values.put(Alarm.Columns.MINUTES, alarm.minutes); |
| values.put(Alarm.Columns.ALARM_TIME, time); |
| values.put(Alarm.Columns.DAYS_OF_WEEK, alarm.daysOfWeek.getCoded()); |
| values.put(Alarm.Columns.VIBRATE, alarm.vibrate); |
| values.put(Alarm.Columns.MESSAGE, alarm.label); |
| |
| // A null alert Uri indicates a silent alarm. |
| values.put(Alarm.Columns.ALERT, alarm.alert == null ? ALARM_ALERT_SILENT |
| : alarm.alert.toString()); |
| |
| return values; |
| } |
| |
| private static void clearSnoozeIfNeeded(Context context, long alarmTime) { |
| // If this alarm fires before the next snooze, clear the snooze to |
| // enable this alarm. |
| SharedPreferences prefs = context.getSharedPreferences(PREFERENCES, 0); |
| |
| // Get the list of snoozed alarms |
| final Set<String> snoozedIds = prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>()); |
| for (String snoozedAlarm : snoozedIds) { |
| final long snoozeTime = prefs.getLong(getAlarmPrefSnoozeTimeKey(snoozedAlarm), 0); |
| if (alarmTime < snoozeTime) { |
| final int alarmId = Integer.parseInt(snoozedAlarm); |
| clearSnoozePreference(context, prefs, alarmId); |
| } |
| } |
| } |
| |
| /** |
| * Return an Alarm object representing the alarm id in the database. |
| * Returns null if no alarm exists. |
| */ |
| public static Alarm getAlarm(ContentResolver contentResolver, int alarmId) { |
| Cursor cursor = contentResolver.query( |
| ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarmId), |
| Alarm.Columns.ALARM_QUERY_COLUMNS, |
| null, null, null); |
| Alarm alarm = null; |
| if (cursor != null) { |
| if (cursor.moveToFirst()) { |
| alarm = new Alarm(cursor); |
| } |
| cursor.close(); |
| } |
| return alarm; |
| } |
| |
| |
| /** |
| * A convenience method to set an alarm in the Alarms |
| * content provider. |
| * @return Time when the alarm will fire. Or < 1 if update failed. |
| */ |
| public static long setAlarm(Context context, Alarm alarm) { |
| ContentValues values = createContentValues(alarm); |
| ContentResolver resolver = context.getContentResolver(); |
| long rowsUpdated = resolver.update( |
| ContentUris.withAppendedId(Alarm.Columns.CONTENT_URI, alarm.id), |
| values, null, null); |
| if (rowsUpdated < 1) { |
| Log.e("Error updating alarm " + alarm); |
| return rowsUpdated; |
| } |
| |
| long timeInMillis = calculateAlarm(alarm); |
| |
| if (alarm.enabled) { |
| // Disable the snooze if we just changed the snoozed alarm. This |
| // only does work if the snoozed alarm is the same as the given |
| // alarm. |
| // TODO: disableSnoozeAlert should have a better name. |
| disableSnoozeAlert(context, alarm.id); |
| |
| // Disable the snooze if this alarm fires before the snoozed alarm. |
| // This works on every alarm since the user most likely intends to |
| // have the modified alarm fire next. |
| clearSnoozeIfNeeded(context, timeInMillis); |
| } |
| |
| setNextAlert(context); |
| |
| return timeInMillis; |
| } |
| |
| /** |
| * A convenience method to enable or disable an alarm. |
| * |
| * @param id corresponds to the _id column |
| * @param enabled corresponds to the ENABLED column |
| */ |
| |
| public static void enableAlarm( |
| final Context context, final int id, boolean enabled) { |
| enableAlarmInternal(context, id, enabled); |
| setNextAlert(context); |
| } |
| |
| private static void enableAlarmInternal(final Context context, |
| final int id, boolean enabled) { |
| enableAlarmInternal(context, getAlarm(context.getContentResolver(), id), |
| enabled); |
| } |
| |
| private static void enableAlarmInternal(final Context context, |
| final Alarm alarm, boolean enabled) { |
| if (alarm == null) { |
| return; |
| } |
| ContentResolver resolver = context.getContentResolver(); |
| |
| ContentValues values = new ContentValues(2); |
| values.put(Alarm.Columns.ENABLED, enabled ? 1 : 0); |
| |
| // If we are enabling the alarm, calculate alarm time since the time |
| // value in Alarm may be old. |
| if (enabled) { |
| long time = 0; |
| if (!alarm.daysOfWeek.isRepeatSet()) { |
| time = calculateAlarm(alarm); |
| } |
| values.put(Alarm.Columns.ALARM_TIME, time); |
| } else { |
| // Clear the snooze if the id matches. |
| disableSnoozeAlert(context, alarm.id); |
| } |
| |
| resolver.update(ContentUris.withAppendedId( |
| Alarm.Columns.CONTENT_URI, alarm.id), values, null, null); |
| } |
| |
| private static Alarm calculateNextAlert(final Context context) { |
| long minTime = Long.MAX_VALUE; |
| long now = System.currentTimeMillis(); |
| final SharedPreferences prefs = context.getSharedPreferences(PREFERENCES, 0); |
| |
| Set<Alarm> alarms = new HashSet<Alarm>(); |
| |
| // We need to to build the list of alarms from both the snoozed list and the scheduled |
| // list. For a non-repeating alarm, when it goes of, it becomes disabled. A snoozed |
| // non-repeating alarm is not in the active list in the database. |
| |
| // first go through the snoozed alarms |
| final Set<String> snoozedIds = prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>()); |
| for (String snoozedAlarm : snoozedIds) { |
| final int alarmId = Integer.parseInt(snoozedAlarm); |
| final Alarm a = getAlarm(context.getContentResolver(), alarmId); |
| alarms.add(a); |
| } |
| |
| // Now add the scheduled alarms |
| final Cursor cursor = getFilteredAlarmsCursor(context.getContentResolver()); |
| if (cursor != null) { |
| try { |
| if (cursor.moveToFirst()) { |
| do { |
| final Alarm a = new Alarm(cursor); |
| alarms.add(a); |
| } while (cursor.moveToNext()); |
| } |
| } finally { |
| cursor.close(); |
| } |
| } |
| |
| Alarm alarm = null; |
| |
| for (Alarm a : alarms) { |
| // A time of 0 indicates this is a repeating alarm, so |
| // calculate the time to get the next alert. |
| if (a.time == 0) { |
| a.time = calculateAlarm(a); |
| } |
| |
| // Update the alarm if it has been snoozed |
| updateAlarmTimeForSnooze(prefs, a); |
| |
| if (a.time < now) { |
| Log.v("Disabling expired alarm set for " + Log.formatTime(a.time)); |
| // Expired alarm, disable it and move along. |
| enableAlarmInternal(context, a, false); |
| continue; |
| } |
| if (a.time < minTime) { |
| minTime = a.time; |
| alarm = a; |
| } |
| } |
| |
| return alarm; |
| } |
| |
| /** |
| * Disables non-repeating alarms that have passed. Called at |
| * boot. |
| */ |
| public static void disableExpiredAlarms(final Context context) { |
| Cursor cur = getFilteredAlarmsCursor(context.getContentResolver()); |
| long now = System.currentTimeMillis(); |
| |
| try { |
| if (cur.moveToFirst()) { |
| do { |
| Alarm alarm = new Alarm(cur); |
| // A time of 0 means this alarm repeats. If the time is |
| // non-zero, check if the time is before now. |
| if (alarm.time != 0 && alarm.time < now) { |
| Log.v("Disabling expired alarm set for " + |
| Log.formatTime(alarm.time)); |
| enableAlarmInternal(context, alarm, false); |
| } |
| } while (cur.moveToNext()); |
| } |
| } finally { |
| cur.close(); |
| } |
| } |
| |
| /** |
| * Called at system startup, on time/timezone change, and whenever |
| * the user changes alarm settings. Activates snooze if set, |
| * otherwise loads all alarms, activates next alert. |
| */ |
| public static void setNextAlert(final Context context) { |
| final Alarm alarm = calculateNextAlert(context); |
| if (alarm != null) { |
| enableAlert(context, alarm, alarm.time); |
| } else { |
| disableAlert(context); |
| } |
| Intent i = new Intent(NEXT_ALARM_TIME_SET); |
| context.sendBroadcast(i); |
| } |
| |
| /** |
| * Sets alert in AlarmManger and StatusBar. This is what will |
| * actually launch the alert when the alarm triggers. |
| * |
| * @param alarm Alarm. |
| * @param atTimeInMillis milliseconds since epoch |
| */ |
| private static void enableAlert(Context context, final Alarm alarm, |
| final long atTimeInMillis) { |
| AlarmManager am = (AlarmManager) |
| context.getSystemService(Context.ALARM_SERVICE); |
| |
| // Intentionally verbose: always log the alarm time to provide useful |
| // information in bug reports. |
| Log.v("Alarm set for id=" + alarm.id + " " + Log.formatTime(atTimeInMillis)); |
| |
| Intent intent = new Intent(ALARM_ALERT_ACTION); |
| |
| // XXX: This is a slight hack to avoid an exception in the remote |
| // AlarmManagerService process. The AlarmManager adds extra data to |
| // this Intent which causes it to inflate. Since the remote process |
| // does not know about the Alarm class, it throws a |
| // ClassNotFoundException. |
| // |
| // To avoid this, we marshall the data ourselves and then parcel a plain |
| // byte[] array. The AlarmReceiver class knows to build the Alarm |
| // object from the byte[] array. |
| Parcel out = Parcel.obtain(); |
| alarm.writeToParcel(out, 0); |
| out.setDataPosition(0); |
| intent.putExtra(ALARM_RAW_DATA, out.marshall()); |
| |
| PendingIntent sender = PendingIntent.getBroadcast( |
| context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT); |
| |
| am.set(AlarmManager.RTC_WAKEUP, atTimeInMillis, sender); |
| |
| setStatusBarIcon(context, true); |
| |
| Calendar c = Calendar.getInstance(); |
| c.setTimeInMillis(atTimeInMillis); |
| String timeString = formatDayAndTime(context, c); |
| saveNextAlarm(context, timeString); |
| } |
| |
| /** |
| * Disables alert in AlarmManager and StatusBar. |
| * |
| * @param context The context |
| */ |
| static void disableAlert(Context context) { |
| AlarmManager am = (AlarmManager) |
| context.getSystemService(Context.ALARM_SERVICE); |
| PendingIntent sender = PendingIntent.getBroadcast( |
| context, 0, new Intent(ALARM_ALERT_ACTION), |
| PendingIntent.FLAG_CANCEL_CURRENT); |
| am.cancel(sender); |
| setStatusBarIcon(context, false); |
| // Intentionally verbose: always log the lack of a next alarm to provide useful |
| // information in bug reports. |
| Log.v("No next alarm"); |
| saveNextAlarm(context, ""); |
| } |
| |
| static void saveSnoozeAlert(final Context context, final int id, |
| final long time) { |
| SharedPreferences prefs = context.getSharedPreferences(PREFERENCES, 0); |
| if (id == INVALID_ALARM_ID) { |
| clearAllSnoozePreferences(context, prefs); |
| } else { |
| final Set<String> snoozedIds = |
| prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>()); |
| snoozedIds.add(Integer.toString(id)); |
| final SharedPreferences.Editor ed = prefs.edit(); |
| ed.putStringSet(PREF_SNOOZE_IDS, snoozedIds); |
| ed.putLong(getAlarmPrefSnoozeTimeKey(id), time); |
| ed.apply(); |
| } |
| // Set the next alert after updating the snooze. |
| setNextAlert(context); |
| } |
| |
| private static String getAlarmPrefSnoozeTimeKey(int id) { |
| return getAlarmPrefSnoozeTimeKey(Integer.toString(id)); |
| } |
| |
| private static String getAlarmPrefSnoozeTimeKey(String id) { |
| return PREF_SNOOZE_TIME + id; |
| } |
| |
| /** |
| * Disable the snooze alert if the given id matches the snooze id. |
| */ |
| static void disableSnoozeAlert(final Context context, final int id) { |
| SharedPreferences prefs = context.getSharedPreferences(PREFERENCES, 0); |
| if (hasAlarmBeenSnoozed(prefs, id)) { |
| // This is the same id so clear the shared prefs. |
| clearSnoozePreference(context, prefs, id); |
| } |
| } |
| |
| // Helper to remove the snooze preference. Do not use clear because that |
| // will erase the clock preferences. Also clear the snooze notification in |
| // the window shade. |
| private static void clearSnoozePreference(final Context context, |
| final SharedPreferences prefs, final int id) { |
| final String alarmStr = Integer.toString(id); |
| final Set<String> snoozedIds = |
| prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>()); |
| if (snoozedIds.contains(alarmStr)) { |
| NotificationManager nm = (NotificationManager) |
| context.getSystemService(Context.NOTIFICATION_SERVICE); |
| nm.cancel(id); |
| } |
| |
| final SharedPreferences.Editor ed = prefs.edit(); |
| snoozedIds.remove(alarmStr); |
| ed.putStringSet(PREF_SNOOZE_IDS, snoozedIds); |
| ed.remove(getAlarmPrefSnoozeTimeKey(alarmStr)); |
| ed.apply(); |
| } |
| |
| private static void clearAllSnoozePreferences(final Context context, |
| final SharedPreferences prefs) { |
| NotificationManager nm = (NotificationManager) |
| context.getSystemService(Context.NOTIFICATION_SERVICE); |
| final Set<String> snoozedIds = |
| prefs.getStringSet(PREF_SNOOZE_IDS, new HashSet<String>()); |
| final SharedPreferences.Editor ed = prefs.edit(); |
| for (String snoozeId : snoozedIds) { |
| nm.cancel(Integer.parseInt(snoozeId)); |
| ed.remove(getAlarmPrefSnoozeTimeKey(snoozeId)); |
| } |
| |
| ed.remove(PREF_SNOOZE_IDS); |
| ed.apply(); |
| } |
| |
| private static boolean hasAlarmBeenSnoozed(final SharedPreferences prefs, final int alarmId) { |
| final Set<String> snoozedIds = prefs.getStringSet(PREF_SNOOZE_IDS, null); |
| |
| // Return true if there a valid snoozed alarmId was saved |
| return snoozedIds != null && snoozedIds.contains(Integer.toString(alarmId)); |
| } |
| |
| /** |
| * Updates the specified Alarm with the additional snooze time. |
| * Returns a boolean indicating whether the alarm was updated. |
| */ |
| private static boolean updateAlarmTimeForSnooze( |
| final SharedPreferences prefs, final Alarm alarm) { |
| if (!hasAlarmBeenSnoozed(prefs, alarm.id)) { |
| // No need to modify the alarm |
| return false; |
| } |
| |
| final long time = prefs.getLong(getAlarmPrefSnoozeTimeKey(alarm.id), -1); |
| // The time in the database is either 0 (repeating) or a specific time |
| // for a non-repeating alarm. Update this value so the AlarmReceiver |
| // has the right time to compare. |
| alarm.time = time; |
| |
| return true; |
| } |
| |
| /** |
| * Tells the StatusBar whether the alarm is enabled or disabled |
| */ |
| private static void setStatusBarIcon(Context context, boolean enabled) { |
| Intent alarmChanged = new Intent("android.intent.action.ALARM_CHANGED"); |
| alarmChanged.putExtra("alarmSet", enabled); |
| context.sendBroadcast(alarmChanged); |
| } |
| |
| private static long calculateAlarm(Alarm alarm) { |
| return calculateAlarm(alarm.hour, alarm.minutes, alarm.daysOfWeek) |
| .getTimeInMillis(); |
| } |
| |
| /** |
| * Given an alarm in hours and minutes, return a time suitable for |
| * setting in AlarmManager. |
| */ |
| static Calendar calculateAlarm(int hour, int minute, |
| Alarm.DaysOfWeek daysOfWeek) { |
| |
| // start with now |
| Calendar c = Calendar.getInstance(); |
| c.setTimeInMillis(System.currentTimeMillis()); |
| |
| int nowHour = c.get(Calendar.HOUR_OF_DAY); |
| int nowMinute = c.get(Calendar.MINUTE); |
| |
| // if alarm is behind current time, advance one day |
| if (hour < nowHour || |
| hour == nowHour && minute <= nowMinute) { |
| c.add(Calendar.DAY_OF_YEAR, 1); |
| } |
| c.set(Calendar.HOUR_OF_DAY, hour); |
| c.set(Calendar.MINUTE, minute); |
| c.set(Calendar.SECOND, 0); |
| c.set(Calendar.MILLISECOND, 0); |
| |
| int addDays = daysOfWeek.getNextAlarm(c); |
| if (addDays > 0) c.add(Calendar.DAY_OF_WEEK, addDays); |
| return c; |
| } |
| |
| static String formatTime(final Context context, int hour, int minute, |
| Alarm.DaysOfWeek daysOfWeek) { |
| Calendar c = calculateAlarm(hour, minute, daysOfWeek); |
| return formatTime(context, c); |
| } |
| |
| /* used by AlarmAlert */ |
| static String formatTime(final Context context, Calendar c) { |
| String format = get24HourMode(context) ? M24 : M12; |
| return (c == null) ? "" : (String)DateFormat.format(format, c); |
| } |
| |
| /** |
| * Shows day and time -- used for lock screen |
| */ |
| private static String formatDayAndTime(final Context context, Calendar c) { |
| String format = get24HourMode(context) ? DM24 : DM12; |
| return (c == null) ? "" : (String)DateFormat.format(format, c); |
| } |
| |
| /** |
| * Save time of the next alarm, as a formatted string, into the system |
| * settings so those who care can make use of it. |
| */ |
| static void saveNextAlarm(final Context context, String timeString) { |
| Log.v("Setting next alarm string in system to " + |
| (TextUtils.isEmpty(timeString) ? "null" : timeString)); |
| Settings.System.putString(context.getContentResolver(), |
| Settings.System.NEXT_ALARM_FORMATTED, |
| timeString); |
| } |
| |
| /** |
| * @return true if clock is set to 24-hour mode |
| */ |
| public static boolean get24HourMode(final Context context) { |
| return android.text.format.DateFormat.is24HourFormat(context); |
| } |
| } |