From 260e36b305a4c3a9bdb31378d700959fedac3484 Mon Sep 17 00:00:00 2001 From: Azuo Date: Sun, 15 Aug 2021 19:13:46 +0800 Subject: [PATCH 1/4] Show & hide all-day events at the right time. --- .../helpers/SettingsStringHelper.kt | 2 +- .../services/UpdateCalendarService.kt | 38 +++++++++++-------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt index 5e38c04..3402c91 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt @@ -99,7 +99,7 @@ object SettingsStringHelper { TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.HIGH.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> { return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 5), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString() } - TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.DEFAULT.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> { + TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.DEFAULT.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) > 15 -> { return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 15), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString() } TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.LOW.rawValue -> { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt index 2ca944b..c584cb6 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt @@ -88,26 +88,31 @@ class UpdateCalendarService : Service() { } else { try { val provider = CalendarProvider(this@UpdateCalendarService) - val data = provider.getInstances(begin.timeInMillis, limit.timeInMillis) + val data = provider.getInstances( + begin.timeInMillis + begin.timeZone.getOffset(begin.timeInMillis).coerceAtMost(0), + limit.timeInMillis + limit.timeZone.getOffset(limit.timeInMillis).coerceAtLeast(0) + ) if (data != null) { val instances = data.list for (instance in instances) { try { val e = provider.getEvent(instance.eventId) - if (e != null && !e.deleted && instance.begin <= limit.timeInMillis && now.timeInMillis < instance.end && !CalendarHelper.getFilteredCalendarIdList() - .contains(e.calendarId) - ) { - if (e.allDay) { - val start = Calendar.getInstance() - start.timeInMillis = instance.begin - val end = Calendar.getInstance() - end.timeInMillis = instance.end - instance.begin = - start.timeInMillis - start.timeZone.getOffset(start.timeInMillis) - instance.end = - end.timeInMillis - end.timeZone.getOffset(end.timeInMillis) - } - + if (e == null || e.deleted || CalendarHelper.getFilteredCalendarIdList().contains(e.calendarId)) + continue + if (e.allDay) { + val start = Calendar.getInstance() + start.timeInMillis = instance.begin + val end = Calendar.getInstance() + end.timeInMillis = instance.end + instance.begin = + start.timeInMillis - start.timeZone.getOffset(start.timeInMillis) + instance.end = + end.timeInMillis - end.timeZone.getOffset(end.timeInMillis) + } + if (instance.begin <= limit.timeInMillis && now.timeInMillis < instance.end) { + /* Following check may result in "fake" all-day events with + * non-UTC start/end time, and therefore cannot be found by + * Calendar when tapped to open details. // Check all day events val startDate = Calendar.getInstance() startDate.timeInMillis = instance.begin @@ -124,6 +129,7 @@ class UpdateCalendarService : Service() { && endDate.get(Calendar.MINUTE) == 0 && endDate.get(Calendar.HOUR_OF_DAY) == 0 ) + */ eventList.add( Event( @@ -133,7 +139,7 @@ class UpdateCalendarService : Service() { startDate = instance.begin, endDate = instance.end, calendarID = e.calendarId.toInt(), - allDay = isAllDay, + allDay = e.allDay, address = e.eventLocation ?: "", selfAttendeeStatus = e.selfAttendeeStatus.toInt(), availability = e.availability From 3ab42fd1633852aef42016f70751e08cf6de3bcf Mon Sep 17 00:00:00 2001 From: azuo Date: Fri, 3 Sep 2021 18:20:01 +0800 Subject: [PATCH 2/4] Correct and improve calendar events updating algorithm. 1. UpdateCalendarService will fetch all events from now to the next fetch time + Preferences.showUntil, so that EventRepository holds all events need to be shown before the next fetch; 2. Every event is updated 1 minute after the corresponding time span, to make the actual time difference consistent with the displayed getRelativeTimeSpanString; 3. Update events only when necessary, eliminate redundant alarms; cancel all update alarms when showEvents is turned off. --- .../anotherwidget/db/EventRepository.kt | 4 +- .../helpers/SettingsStringHelper.kt | 32 +--- .../receivers/NewCalendarEventReceiver.kt | 3 +- .../receivers/UpdatesReceiver.kt | 177 ++++++++---------- .../receivers/WeatherReceiver.kt | 2 - .../services/UpdateCalendarService.kt | 15 +- .../ui/fragments/tabs/PreferencesFragment.kt | 2 + 7 files changed, 102 insertions(+), 133 deletions(-) diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/db/EventRepository.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/db/EventRepository.kt index 342d107..9811857 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/db/EventRepository.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/db/EventRepository.kt @@ -64,7 +64,7 @@ class EventRepository(val context: Context) { else -> add(Calendar.HOUR, 6) } } - val event = if (nextEvent != null && nextEvent.endDate > now && nextEvent.startDate < limit.timeInMillis) { + val event = if (nextEvent != null && nextEvent.endDate > now && nextEvent.startDate <= limit.timeInMillis) { nextEvent } else { val events = getEvents() @@ -105,7 +105,6 @@ class EventRepository(val context: Context) { } else { resetNextEventData() } - UpdatesReceiver.setUpdates(context) MainWidget.updateWidget(context) } @@ -121,7 +120,6 @@ class EventRepository(val context: Context) { } else { resetNextEventData() } - UpdatesReceiver.setUpdates(context) MainWidget.updateWidget(context) } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt index 3402c91..6f511fa 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/helpers/SettingsStringHelper.kt @@ -88,19 +88,17 @@ object SettingsStringHelper { fun getDifferenceText(context: Context, now: Long, start: Long): String { val nowDate = DateTime(now) val eventDate = DateTime(start) - - var difference = start - now - difference += 60 * 1000 - (difference % (60 * 1000)) + val difference = start - now when { difference <= 0 -> { return "" } - TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.HIGH.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) > 5 -> { - return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 5), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString() + TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.HIGH.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) >= 5 -> { + return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - TimeUnit.MILLISECONDS.toMinutes(difference) % 5), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString() } - TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.DEFAULT.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) > 15 -> { - return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - 1 - (TimeUnit.MILLISECONDS.toMinutes(difference) - 1) % 15), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString() + TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.DEFAULT.rawValue && TimeUnit.MILLISECONDS.toMinutes(difference) >= 15 -> { + return DateUtils.getRelativeTimeSpanString(start, start - 1000 * 60 * (TimeUnit.MILLISECONDS.toMinutes(difference) - TimeUnit.MILLISECONDS.toMinutes(difference) % 15), DateUtils.MINUTE_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString() } TimeUnit.MILLISECONDS.toHours(difference) < 1 && Preferences.widgetUpdateFrequency == Constants.WidgetUpdateFrequency.LOW.rawValue -> { return context.getString(R.string.soon) @@ -109,22 +107,7 @@ object SettingsStringHelper { return context.getString(R.string.now) } TimeUnit.MILLISECONDS.toHours(difference) < 12 -> { - val minutes = TimeUnit.MILLISECONDS.toMinutes(difference) - 60 * TimeUnit.MILLISECONDS.toHours(difference) - return if (minutes < 1 || minutes > 30) { - DateUtils.getRelativeTimeSpanString( - start, - now - 1000 * 60 * 40, - DateUtils.HOUR_IN_MILLIS, - DateUtils.FORMAT_ABBREV_RELATIVE - ).toString() - } else { - DateUtils.getRelativeTimeSpanString( - start, - now, - DateUtils.HOUR_IN_MILLIS, - DateUtils.FORMAT_ABBREV_RELATIVE - ).toString() - } + return DateUtils.getRelativeTimeSpanString(start, now, DateUtils.HOUR_IN_MILLIS, DateUtils.FORMAT_ABBREV_RELATIVE).toString() } eventDate.dayOfYear == nowDate.plusDays(1).dayOfYear -> { return String.format("%s", context.getString(R.string.tomorrow)) @@ -143,9 +126,6 @@ object SettingsStringHelper { val nowDate = DateTime(now) val eventDate = DateTime(start) - var difference = start - now - difference += 60 * 1000 - (difference % (60 * 1000)) - return when (eventDate.dayOfYear) { nowDate.dayOfYear -> { "" diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/NewCalendarEventReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/NewCalendarEventReceiver.kt index 3ff5e57..b807020 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/NewCalendarEventReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/NewCalendarEventReceiver.kt @@ -13,8 +13,7 @@ class NewCalendarEventReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { val eventRepository = EventRepository(context) when (intent.action) { - Intent.ACTION_PROVIDER_CHANGED, - Intent.ACTION_TIME_CHANGED -> { + Intent.ACTION_PROVIDER_CHANGED -> { CalendarHelper.updateEventList(context) } Actions.ACTION_GO_TO_NEXT_EVENT -> { diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt index 36330f4..b1dc382 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt @@ -38,6 +38,7 @@ class UpdatesReceiver : BroadcastReceiver() { "com.sec.android.widgetapp.APPWIDGET_RESIZE", AlarmManager.ACTION_NEXT_ALARM_CLOCK_CHANGED, Actions.ACTION_ALARM_UPDATE, + Actions.ACTION_UPDATE_GREETINGS, Actions.ACTION_TIME_UPDATE -> { MainWidget.updateWidget(context) if (intent.hasExtra(EVENT_ID)) { @@ -49,9 +50,6 @@ class UpdatesReceiver : BroadcastReceiver() { ActiveNotificationsHelper.clearLastNotification(context) MainWidget.updateWidget(context) } - Actions.ACTION_UPDATE_GREETINGS -> { - MainWidget.updateWidget(context) - } Actions.ACTION_REFRESH -> { GlobalScope.launch(Dispatchers.IO) { @@ -69,7 +67,25 @@ class UpdatesReceiver : BroadcastReceiver() { fun setUpdates(context: Context, eventId: Long? = null) { val eventRepository = EventRepository(context) if (eventId == null) { - removeUpdates(context) + with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { + setExact( + AlarmManager.RTC, + Calendar.getInstance().apply { + set(Calendar.MILLISECOND, 0) + set(Calendar.SECOND, 0) + set(Calendar.MINUTE, 0) + set(Calendar.HOUR_OF_DAY, 0) + add(Calendar.DATE, 1) + }.timeInMillis, + PendingIntent.getBroadcast( + context, + 0, + Intent(context, UpdatesReceiver::class.java).apply { + action = Actions.ACTION_CALENDAR_UPDATE + }, + 0) + ) + } eventRepository.getFutureEvents().forEach { event -> setEventUpdate(context, event) @@ -84,109 +100,80 @@ class UpdatesReceiver : BroadcastReceiver() { } private fun setEventUpdate(context: Context, event: Event) { - with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { - val now = Calendar.getInstance().apply { - set(Calendar.SECOND, 0) - set(Calendar.MILLISECOND, 0) - } - val diff = Period(now.timeInMillis, event.startDate) - val limit = when (Preferences.showUntil) { - 0 -> 1000 * 60 * 60 * 3 - 1 -> 1000 * 60 * 60 * 6 - 2 -> 1000 * 60 * 60 * 12 - 3 -> 1000 * 60 * 60 * 24 - 4 -> 1000 * 60 * 60 * 24 * 3 - 5 -> 1000 * 60 * 60 * 24 * 7 - 6 -> 1000 * 60 * 30 - 7 -> 1000 * 60 * 60 - else -> 1000 * 60 * 60 * 6 - } - if (event.startDate <= limit) { - if (event.startDate > now.timeInMillis) { - // Update the widget every hour till the event - if (diff.hours == 0) { - var minutes = 0 - when (Preferences.widgetUpdateFrequency) { - Constants.WidgetUpdateFrequency.DEFAULT.rawValue -> { - minutes = when { - diff.minutes > 50 -> 50 - diff.minutes > 30 -> 30 - diff.minutes > 15 -> 15 - else -> 0 - } - } - Constants.WidgetUpdateFrequency.HIGH.rawValue -> { - minutes = diff.minutes - (diff.minutes % 5) - } + val now = Calendar.getInstance().apply { + set(Calendar.SECOND, 0) + set(Calendar.MILLISECOND, 0) + } + val diff = Period(now.timeInMillis, event.startDate, org.joda.time.PeriodType.time()) + val limit = when (Preferences.showUntil) { + 0 -> 1000 * 60 * 60 * 3 + 1 -> 1000 * 60 * 60 * 6 + 2 -> 1000 * 60 * 60 * 12 + 3 -> 1000 * 60 * 60 * 24 + 4 -> 1000 * 60 * 60 * 24 * 3 + 5 -> 1000 * 60 * 60 * 24 * 7 + 6 -> 1000 * 60 * 30 + 7 -> 1000 * 60 * 60 + else -> 1000 * 60 * 60 * 6 + } + val fireTime = when { + event.startDate <= now.timeInMillis + -> event.endDate + event.startDate > now.timeInMillis + limit + -> event.startDate - limit + event.allDay + -> event.startDate + diff.hours > 12 + -> event.startDate - 12 * 1000 * 60 * 60 + 1000 * 60 + diff.hours > 0 + -> event.startDate - diff.hours * 1000 * 60 * 60 + 1000 * 60 + else + -> event.startDate - 1000 * 60 * when (Preferences.widgetUpdateFrequency) { + Constants.WidgetUpdateFrequency.DEFAULT.rawValue -> { + when { + diff.minutes >= 45 -> 44 + diff.minutes >= 30 -> 29 + diff.minutes >= 15 -> 14 + else -> 0 } - setExact( - AlarmManager.RTC, - if (event.startDate - minutes * 1000 * 60 > (now.timeInMillis + 120 * 1000)) event.startDate - 60 * 1000 * minutes else now.timeInMillis + 120000, - PendingIntent.getBroadcast( - context, - event.eventID.toInt(), - Intent(context, UpdatesReceiver::class.java).apply { - action = Actions.ACTION_TIME_UPDATE - putExtra(EVENT_ID, event.eventID) - }, - PendingIntent.FLAG_UPDATE_CURRENT - ) - ) - } else { - setExact( - AlarmManager.RTC, - event.startDate - diff.hours * 1000 * 60 * 60 + if (diff.minutes > 30) (-30) else (+30), - PendingIntent.getBroadcast( - context, - event.eventID.toInt(), - Intent(context, UpdatesReceiver::class.java).apply { - action = Actions.ACTION_TIME_UPDATE - putExtra(EVENT_ID, event.eventID) - }, - PendingIntent.FLAG_UPDATE_CURRENT - ) - ) } - } else { - // Update the widget one second after the event is finished - val fireTime = - if (event.endDate > now.timeInMillis + 120 * 1000) event.endDate else now.timeInMillis + 120000 - setExact( - AlarmManager.RTC, - fireTime, - PendingIntent.getBroadcast( - context, - event.eventID.toInt(), - Intent(context, UpdatesReceiver::class.java).apply { - action = Actions.ACTION_TIME_UPDATE - }, - 0 - ) - ) + Constants.WidgetUpdateFrequency.HIGH.rawValue -> { + when { + diff.minutes >= 5 -> diff.minutes - diff.minutes % 5 - 1 + else -> 0 + } + } + else -> 0 } - } else { - setExact( - AlarmManager.RTC, - if (event.startDate - limit > now.timeInMillis + 120 * 1000) event.startDate - limit else now.timeInMillis + 120000, - PendingIntent.getBroadcast( - context, - event.eventID.toInt(), - Intent(context, UpdatesReceiver::class.java).apply { - action = Actions.ACTION_TIME_UPDATE + } + with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { + setExact( + AlarmManager.RTC, + fireTime.coerceAtLeast(now.timeInMillis + 1000 * 60), + PendingIntent.getBroadcast( + context, + event.eventID.toInt(), + Intent(context, UpdatesReceiver::class.java).apply { + action = Actions.ACTION_TIME_UPDATE + if (event.startDate > now.timeInMillis) putExtra(EVENT_ID, event.eventID) - }, - PendingIntent.FLAG_UPDATE_CURRENT - ) + }, + PendingIntent.FLAG_UPDATE_CURRENT ) - } + ) } } fun removeUpdates(context: Context) { with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { + cancel(PendingIntent.getBroadcast(context, 0, Intent(context, UpdatesReceiver::class.java).apply { + action = Actions.ACTION_CALENDAR_UPDATE + }, 0)) val eventRepository = EventRepository(context) eventRepository.getFutureEvents().forEach { - cancel(PendingIntent.getBroadcast(context, it.eventID.toInt(), Intent(context, UpdatesReceiver::class.java), 0)) + cancel(PendingIntent.getBroadcast(context, it.eventID.toInt(), Intent(context, UpdatesReceiver::class.java).apply { + action = Actions.ACTION_TIME_UPDATE + }, 0)) } eventRepository.close() } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/WeatherReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/WeatherReceiver.kt index 4b6f6eb..92f068b 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/WeatherReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/WeatherReceiver.kt @@ -35,8 +35,6 @@ class WeatherReceiver : BroadcastReceiver() { companion object { private const val MINUTE = 60 * 1000L fun setUpdates(context: Context) { - removeUpdates(context) - if (Preferences.showWeather) { val interval = MINUTE * when (Preferences.weatherRefreshPeriod) { 0 -> 30 diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt index c584cb6..b69f0b9 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt @@ -55,18 +55,20 @@ class UpdateCalendarService : Service() { job?.cancel() job = GlobalScope.launch(Dispatchers.IO) { + UpdatesReceiver.removeUpdates(this@UpdateCalendarService) + val eventRepository = EventRepository(this@UpdateCalendarService) if (Preferences.showEvents) { val eventList = ArrayList() + // fetch all events from now to next ACTION_CALENDAR_UPDATE + limit val now = Calendar.getInstance() - val begin = Calendar.getInstance().apply { + val limit = Calendar.getInstance().apply { set(Calendar.MILLISECOND, 0) set(Calendar.SECOND, 0) set(Calendar.MINUTE, 0) set(Calendar.HOUR_OF_DAY, 0) - } - val limit = Calendar.getInstance().apply { + add(Calendar.DATE, 1) when (Preferences.showUntil) { 0 -> add(Calendar.HOUR, 3) 1 -> add(Calendar.HOUR, 6) @@ -85,11 +87,13 @@ class UpdateCalendarService : Service() { ) ) { eventRepository.resetNextEventData() + eventRepository.clearEvents() } else { try { val provider = CalendarProvider(this@UpdateCalendarService) + // apply time zone offset to correctly fetch all-day events val data = provider.getInstances( - begin.timeInMillis + begin.timeZone.getOffset(begin.timeInMillis).coerceAtMost(0), + now.timeInMillis + now.timeZone.getOffset(now.timeInMillis).coerceAtMost(0), limit.timeInMillis + limit.timeZone.getOffset(limit.timeInMillis).coerceAtLeast(0) ) if (data != null) { @@ -170,13 +174,14 @@ class UpdateCalendarService : Service() { } } else { eventRepository.resetNextEventData() + eventRepository.clearEvents() } + eventRepository.close() UpdatesReceiver.setUpdates(this@UpdateCalendarService) MainWidget.updateWidget(this@UpdateCalendarService) EventBus.getDefault().post(MainFragment.UpdateUiMessageEvent()) - eventRepository.close() stopSelf() } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/PreferencesFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/PreferencesFragment.kt index 3c6c9d2..74a4c97 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/PreferencesFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/PreferencesFragment.kt @@ -23,6 +23,7 @@ import com.tommasoberlose.anotherwidget.components.MaterialBottomSheetDialog import com.tommasoberlose.anotherwidget.databinding.FragmentPreferencesBinding import com.tommasoberlose.anotherwidget.global.Preferences import com.tommasoberlose.anotherwidget.helpers.CalendarHelper +import com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver import com.tommasoberlose.anotherwidget.receivers.WeatherReceiver import com.tommasoberlose.anotherwidget.ui.activities.MainActivity import com.tommasoberlose.anotherwidget.ui.viewmodels.MainViewModel @@ -123,6 +124,7 @@ class PreferencesFragment : Fragment() { requireCalendarPermission() } else { Preferences.showEvents = enabled + UpdatesReceiver.removeUpdates(requireContext()) } } From 818b4ec0ba00a3a670f5d1a12ddb337a42e174cd Mon Sep 17 00:00:00 2001 From: azuo Date: Sat, 4 Sep 2021 18:35:39 +0800 Subject: [PATCH 3/4] Avoid redundant updates. --- .../anotherwidget/receivers/UpdatesReceiver.kt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt index b1dc382..c9faa40 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt @@ -67,6 +67,7 @@ class UpdatesReceiver : BroadcastReceiver() { fun setUpdates(context: Context, eventId: Long? = null) { val eventRepository = EventRepository(context) if (eventId == null) { + // schedule ACTION_CALENDAR_UPDATE at midnight (ACTION_DATE_CHANGED no longer works) with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { setExact( AlarmManager.RTC, @@ -121,6 +122,8 @@ class UpdatesReceiver : BroadcastReceiver() { -> event.endDate event.startDate > now.timeInMillis + limit -> event.startDate - limit + !Preferences.showDiffTime + -> return event.allDay -> event.startDate diff.hours > 12 @@ -146,6 +149,14 @@ class UpdatesReceiver : BroadcastReceiver() { else -> 0 } } + // avoid redundant updates at midnight + if (Calendar.getInstance().run { + timeInMillis = fireTime + get(Calendar.MILLISECOND) == 0 && + get(Calendar.SECOND) == 0 && + get(Calendar.MINUTE) == 0 && + get(Calendar.HOUR_OF_DAY) == 0 + }) return with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { setExact( AlarmManager.RTC, From 9f47d626a9972734bb52457ece4d386923bb5f29 Mon Sep 17 00:00:00 2001 From: azuo Date: Mon, 13 Sep 2021 23:24:58 +0800 Subject: [PATCH 4/4] setExact is more reliable than setRepeating on some ROMs (e.g., MIUI). --- .../receivers/UpdatesReceiver.kt | 21 +++++++++++-------- .../receivers/WeatherReceiver.kt | 17 +++++++-------- .../services/UpdateCalendarService.kt | 1 + .../ui/activities/MainActivity.kt | 1 + .../ui/fragments/tabs/CalendarFragment.kt | 5 +++-- .../ui/fragments/tabs/PreferencesFragment.kt | 2 ++ 6 files changed, 26 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt index c9faa40..2997b1b 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/UpdatesReceiver.kt @@ -65,6 +65,8 @@ class UpdatesReceiver : BroadcastReceiver() { const val EVENT_ID = "EVENT_ID" fun setUpdates(context: Context, eventId: Long? = null) { + if (!Preferences.showEvents) + return val eventRepository = EventRepository(context) if (eventId == null) { // schedule ACTION_CALENDAR_UPDATE at midnight (ACTION_DATE_CHANGED no longer works) @@ -84,7 +86,8 @@ class UpdatesReceiver : BroadcastReceiver() { Intent(context, UpdatesReceiver::class.java).apply { action = Actions.ACTION_CALENDAR_UPDATE }, - 0) + 0 + ) ) } @@ -149,14 +152,14 @@ class UpdatesReceiver : BroadcastReceiver() { else -> 0 } } - // avoid redundant updates at midnight - if (Calendar.getInstance().run { - timeInMillis = fireTime - get(Calendar.MILLISECOND) == 0 && - get(Calendar.SECOND) == 0 && - get(Calendar.MINUTE) == 0 && - get(Calendar.HOUR_OF_DAY) == 0 - }) return + // no need to schedule updates after the next ACTION_CALENDAR_UPDATE + if (Calendar.getInstance().apply { + set(Calendar.MILLISECOND, 0) + set(Calendar.SECOND, 0) + set(Calendar.MINUTE, 0) + set(Calendar.HOUR_OF_DAY, 0) + add(Calendar.DATE, 1) + }.timeInMillis <= fireTime) return with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { setExact( AlarmManager.RTC, diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/WeatherReceiver.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/WeatherReceiver.kt index 92f068b..f352b28 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/WeatherReceiver.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/receivers/WeatherReceiver.kt @@ -22,13 +22,8 @@ class WeatherReceiver : BroadcastReceiver() { Intent.ACTION_MY_PACKAGE_REPLACED, Intent.ACTION_TIMEZONE_CHANGED, Intent.ACTION_LOCALE_CHANGED, - Intent.ACTION_TIME_CHANGED -> setUpdates(context) - - Actions.ACTION_WEATHER_UPDATE -> { - GlobalScope.launch(Dispatchers.IO) { - WeatherHelper.updateWeather(context) - } - } + Intent.ACTION_TIME_CHANGED, + Actions.ACTION_WEATHER_UPDATE -> setUpdates(context) } } @@ -46,13 +41,15 @@ class WeatherReceiver : BroadcastReceiver() { else -> 60 } with(context.getSystemService(Context.ALARM_SERVICE) as AlarmManager) { - setRepeating( + setExact( AlarmManager.RTC, - Calendar.getInstance().timeInMillis, - interval, + System.currentTimeMillis() + interval, PendingIntent.getBroadcast(context, 0, Intent(context, WeatherReceiver::class.java).apply { action = Actions.ACTION_WEATHER_UPDATE }, 0) ) } + GlobalScope.launch(Dispatchers.IO) { + WeatherHelper.updateWeather(context) + } } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt index b69f0b9..cef9fe0 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/services/UpdateCalendarService.kt @@ -88,6 +88,7 @@ class UpdateCalendarService : Service() { ) { eventRepository.resetNextEventData() eventRepository.clearEvents() + Preferences.showEvents = false } else { try { val provider = CalendarProvider(this@UpdateCalendarService) diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/MainActivity.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/MainActivity.kt index 6435d89..0e080df 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/MainActivity.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/activities/MainActivity.kt @@ -140,6 +140,7 @@ class MainActivity : AppCompatActivity(), SharedPreferences.OnSharedPreferenceCh if (Preferences.showEvents && !checkGrantedPermission(Manifest.permission.READ_CALENDAR)) { Preferences.showEvents = false + com.tommasoberlose.anotherwidget.receivers.UpdatesReceiver.removeUpdates(this) } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/CalendarFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/CalendarFragment.kt index d6d3018..b6b7034 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/CalendarFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/CalendarFragment.kt @@ -182,7 +182,7 @@ class CalendarFragment : Fragment() { binding.showAllDayToggle.setOnCheckedChangeListener { _, isChecked -> Preferences.calendarAllDay = isChecked - MainWidget.updateWidget(requireContext()) + updateCalendar() } binding.actionChangeAttendeeFilter.setOnClickListener { @@ -227,7 +227,7 @@ class CalendarFragment : Fragment() { binding.showOnlyBusyEventsToggle.setOnCheckedChangeListener { _, isChecked -> Preferences.showOnlyBusyEvents = isChecked - MainWidget.updateWidget(requireContext()) + updateCalendar() } binding.actionShowDiffTime.setOnClickListener { @@ -254,6 +254,7 @@ class CalendarFragment : Fragment() { .addItem(getString(R.string.settings_widget_update_frequency_low), Constants.WidgetUpdateFrequency.LOW.rawValue) .addOnSelectItemListener { value -> Preferences.widgetUpdateFrequency = value + updateCalendar() }.show() } } diff --git a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/PreferencesFragment.kt b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/PreferencesFragment.kt index 74a4c97..c531a40 100644 --- a/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/PreferencesFragment.kt +++ b/app/src/main/java/com/tommasoberlose/anotherwidget/ui/fragments/tabs/PreferencesFragment.kt @@ -135,6 +135,8 @@ class PreferencesFragment : Fragment() { binding.showWeatherSwitch.setOnCheckedChangeListener { _, enabled: Boolean -> Preferences.showWeather = enabled if (enabled) { + Preferences.weatherProviderError = "" + Preferences.weatherProviderLocationError = "" WeatherReceiver.setUpdates(requireContext()) } else { WeatherReceiver.removeUpdates(requireContext())