Best way to reset a database value every week on specific day (Android - Room)

272 Views Asked by At

I'm working on an Android app that has a functionality that is weekly basis, that is, every day of the week the user has to mark as done the day. This value is a boolean on my database, that is initialized with false, and is set to true when the user clicks on the checkbox. Everything is working fine.

But my problem is that I need to "reset" this boolean value to false on all the seven days of the week every time a new week begins. I don't need to have records of the past weeks. All that matters is the actual week (Sunday to Saturday).

It's a very simple task, I only need to do this:

for(WeekDay day: dao.getWeekDays()){
            day.setDone(false);
            dao.updateWeekDay(day); //update the value in database
        }

So, I did some research (I'm new to android) and find out that Android has different schedule services like JobScheduler or AlarmManager. My app is designed to Android 10+ (API 29+). What do you think is the best solution for my problem? It's a very simple task (it won't take too much battery, internet,...) and I need to do this in a specific day (Sunday) every week. Also, this task needs to be done as soon as it possible, even if the phone is turned off on Sunday. It doesn't need to be a background service, but I need to guarantee that when the user opens the app and it's a new week, that method needs to be call before, but only if it had not been call in the actual week before.

Anyone has ideas?

1

There are 1 best solutions below

0
On BEST ANSWER

Ok, I think I found a simple solution for my problem, based on other similar answers I read. I just need to run these function every time the app starts. I didn't need to use any background service, like WorkManager. I only need to store in SharedPreferences the last date when the system did a reset in the values. Then, every time I open the app, it checks if today is in a different week from the last reset day. If it's true, then I run that "for cycle" in the question and update the last reset day to today in the SharedPreferences. If it's false, I do nothing.

The method inSameCalendarWeek checks if the day is in the same week from the same year of today (Locale.US guarantees that a week starts on Sunday. But I could change that to Locale.getDefault() to be more flexible). Also, for example, if December 31 is in the same week of January 1, even if they are in different years, the method will return true.

private void checkAndResetDoneDays() {
        long lastResetDay = settings.getLong(LAST_DAY_RESET, 0);
        LocalDate date = Instant.ofEpochMilli(lastResetDay).atZone(ZoneId.systemDefault()).toLocalDate();
        if (!inSameCalendarWeek(date)) {
            resetDoneDays();
            settings.edit()
                    .putLong(LAST_DAY_RESET, LocalDate.now(ZoneId.systemDefault()).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli())
                    .commit();
        }
    }

public boolean inSameCalendarWeek(LocalDate firstDate) {
        LocalDate secondDate = LocalDate.now(ZoneId.systemDefault());
        // get a reference to the system of calendar weeks in US Locale (to guarantee that week starts on Sunday)
        WeekFields weekFields = WeekFields.of(Locale.US);
        // find out the calendar week for each of the dates
        int firstDatesCalendarWeek = firstDate.get(weekFields.weekOfWeekBasedYear());
        int secondDatesCalendarWeek = secondDate.get(weekFields.weekOfWeekBasedYear());
        /*
         * find out the week based year, too,
         * two dates might be both in a calendar week number 1 for example,
         * but in different years
         */
        int firstWeekBasedYear = firstDate.get(weekFields.weekBasedYear());
        int secondWeekBasedYear = secondDate.get(weekFields.weekBasedYear());
        // return if they are equal or not
        return firstDatesCalendarWeek == secondDatesCalendarWeek
                && firstWeekBasedYear == secondWeekBasedYear;
    }