From 4dd77463fb29a50bce248d91ab9b6b2cd987f159 Mon Sep 17 00:00:00 2001 From: Kristian Tashkov Date: Sun, 6 Sep 2020 01:25:46 +0300 Subject: [PATCH] Update widgets at midnight (#634) --- .../org/isoron/uhabits/HabitsApplication.kt | 1 + .../isoron/uhabits/intents/IntentScheduler.kt | 13 +++++++++---- .../uhabits/intents/PendingIntentFactory.kt | 8 ++++++++ .../uhabits/receivers/WidgetReceiver.java | 17 +++++++++++++++-- .../org/isoron/uhabits/widgets/WidgetUpdater.kt | 10 +++++++++- .../core/reminders/ReminderScheduler.java | 2 ++ .../isoron/uhabits/core/utils/DateUtils.java | 7 ++++++- .../uhabits/core/utils/DateUtilsTest.java | 1 + 8 files changed, 51 insertions(+), 8 deletions(-) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.kt index df162766c..a2c2b0e99 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/HabitsApplication.kt @@ -62,6 +62,7 @@ class HabitsApplication : Application() { widgetUpdater = component.widgetUpdater widgetUpdater.startListening() + widgetUpdater.scheduleStartDayWidgetUpdate() reminderScheduler = component.reminderScheduler reminderScheduler.startListening() diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt index 934942f15..2882d3022 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/IntentScheduler.kt @@ -45,7 +45,7 @@ class IntentScheduler private val manager = context.getSystemService(ALARM_SERVICE) as AlarmManager - fun schedule(timestamp: Long, intent: PendingIntent) { + fun schedule(timestamp: Long, intent: PendingIntent, alarmType: Int) { Log.d("IntentScheduler", "timestamp=" + timestamp + " current=" + System.currentTimeMillis()) if (timestamp < System.currentTimeMillis()) { @@ -54,19 +54,24 @@ class IntentScheduler return; } if (SDK_INT >= M) - manager.setExactAndAllowWhileIdle(RTC_WAKEUP, timestamp, intent) + manager.setExactAndAllowWhileIdle(alarmType, timestamp, intent) else - manager.setExact(RTC_WAKEUP, timestamp, intent) + manager.setExact(alarmType, timestamp, intent) } override fun scheduleShowReminder(reminderTime: Long, habit: Habit, timestamp: Long) { val intent = pendingIntents.showReminder(habit, reminderTime, timestamp) - schedule(reminderTime, intent) + schedule(reminderTime, intent, RTC_WAKEUP) logReminderScheduled(habit, reminderTime) } + override fun scheduleWidgetUpdate(updateTime: Long) { + val intent = pendingIntents.updateWidgets() + schedule(updateTime, intent, RTC) + } + override fun log(componentName: String, msg: String) { Log.d(componentName, msg) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt index 0901a0836..befdc7be0 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/intents/PendingIntentFactory.kt @@ -103,4 +103,12 @@ class PendingIntentFactory if (timestamp != null) putExtra("timestamp", timestamp) }, FLAG_UPDATE_CURRENT) + + fun updateWidgets(): PendingIntent = + PendingIntent.getBroadcast( + context, 0, + Intent(context, WidgetReceiver::class.java).apply { + action = WidgetReceiver.ACTION_UPDATE_WIDGETS_VALUE + }, + FLAG_UPDATE_CURRENT) } diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/WidgetReceiver.java b/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/WidgetReceiver.java index e5dec0218..7320a40dd 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/WidgetReceiver.java +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/receivers/WidgetReceiver.java @@ -26,6 +26,7 @@ import org.isoron.uhabits.core.preferences.*; import org.isoron.uhabits.core.ui.widgets.*; import org.isoron.uhabits.intents.*; +import org.isoron.uhabits.widgets.*; import dagger.*; @@ -48,6 +49,9 @@ public class WidgetReceiver extends BroadcastReceiver public static final String ACTION_TOGGLE_REPETITION = "org.isoron.uhabits.ACTION_TOGGLE_REPETITION"; + public static final String ACTION_UPDATE_WIDGETS_VALUE = + "org.isoron.uhabits.ACTION_UPDATE_WIDGETS_VALUE"; + private static final String TAG = "WidgetReceiver"; @Override @@ -64,13 +68,17 @@ public void onReceive(final Context context, Intent intent) IntentParser parser = app.getComponent().getIntentParser(); WidgetBehavior controller = component.getWidgetController(); Preferences prefs = app.getComponent().getPreferences(); + WidgetUpdater widgetUpdater = app.getComponent().getWidgetUpdater(); Log.i(TAG, String.format("Received intent: %s", intent.toString())); try { - IntentParser.CheckmarkIntentData data; - data = parser.parseCheckmarkIntent(intent); + IntentParser.CheckmarkIntentData data = null; + if (intent.getAction() != ACTION_UPDATE_WIDGETS_VALUE) + { + data = parser.parseCheckmarkIntent(intent); + } switch (intent.getAction()) { @@ -100,6 +108,11 @@ public void onReceive(final Context context, Intent intent) controller.onRemoveRepetition(data.getHabit(), data.getTimestamp()); break; + + case ACTION_UPDATE_WIDGETS_VALUE: + widgetUpdater.updateWidgets(); + widgetUpdater.scheduleStartDayWidgetUpdate(); + break; } } catch (RuntimeException e) diff --git a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt index b8293582a..3f84f4fc3 100644 --- a/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt +++ b/android/uhabits-android/src/main/java/org/isoron/uhabits/widgets/WidgetUpdater.kt @@ -25,6 +25,8 @@ import org.isoron.androidbase.* import org.isoron.uhabits.core.commands.* import org.isoron.uhabits.core.preferences.* import org.isoron.uhabits.core.tasks.* +import org.isoron.uhabits.core.utils.* +import org.isoron.uhabits.intents.* import javax.inject.* /** @@ -36,7 +38,8 @@ class WidgetUpdater @AppContext private val context: Context, private val commandRunner: CommandRunner, private val taskRunner: TaskRunner, - private val widgetPrefs: WidgetPreferences + private val widgetPrefs: WidgetPreferences, + private val intentScheduler: IntentScheduler ) : CommandRunner.Listener { override fun onCommandExecuted(command: Command, refreshKey: Long?) { @@ -60,6 +63,11 @@ class WidgetUpdater commandRunner.removeListener(this) } + fun scheduleStartDayWidgetUpdate() { + val timestamp = DateUtils.getStartOfTomorrow() + intentScheduler.scheduleWidgetUpdate(timestamp); + } + fun updateWidgets(modifiedHabitId: Long?) { taskRunner.execute { updateWidgets(modifiedHabitId, CheckmarkWidgetProvider::class.java) diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java index ab00c78eb..6dfb41e38 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/reminders/ReminderScheduler.java @@ -164,6 +164,8 @@ public interface SystemScheduler { void scheduleShowReminder(long reminderTime, Habit habit, long timestamp); + void scheduleWidgetUpdate(long updateTime); + void log(String componentName, String msg); } } diff --git a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java index 796a12740..e10625d05 100644 --- a/android/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java +++ b/android/uhabits-core/src/main/java/org/isoron/uhabits/core/utils/DateUtils.java @@ -175,9 +175,14 @@ public static long getStartOfToday() return getStartOfDay(getLocalTime()); } + public static long getStartOfTomorrow() + { + return getUpcomingTimeInMillis(0, 0); + } + public static long millisecondsUntilTomorrow() { - return getStartOfToday() + DAY_LENGTH - getLocalTime(); + return getStartOfTomorrow() - getLocalTime(); } public static GregorianCalendar getStartOfTodayCalendar() diff --git a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/utils/DateUtilsTest.java b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/utils/DateUtilsTest.java index ee7db003a..84c942cb4 100644 --- a/android/uhabits-core/src/test/java/org/isoron/uhabits/core/utils/DateUtilsTest.java +++ b/android/uhabits-core/src/test/java/org/isoron/uhabits/core/utils/DateUtilsTest.java @@ -164,6 +164,7 @@ public void testTruncate_year() @Test public void testMillisecondsUntilTomorrow() throws Exception { + DateUtils.setFixedTimeZone(TimeZone.getTimeZone("GMT")); DateUtils.setFixedLocalTime(unixTime(2017, JANUARY, 1, 23, 59)); assertThat(DateUtils.millisecondsUntilTomorrow(), equalTo(60000L));