How to delete SharedPreferences automatically after one month? - android

I want to delete SharedPreferences, if they exist, after one month automatically. I could not find any solutions. Is this possible to make?
Thanks a lot.

It depends.
The easiest way is to delete it when the user starts the app.
When the apps is created, you check the SharedPreferences for the last updated time.
If it's null (the first time), you save the current time in milliseconds as a long.
If it's not null, you read it and compare it against the current time. If it less than a month, you do nothing. If it's more than a month, you clear the shared preferences and, after clearing it, insert the new time.
Something like:
long lastUpdate = sharedPreferences.getLong(LAST_UPDATE, -1);
if(lastUpdate == -1) {
//First time
sharedPreferences.edit().putLong(LAST_UPDATE, System.currentTimeMillis()).apply();
} else {
boolean isMoreThanAMonth = //Here you should do the math. it depends, you want to consider a month like 30 days, or you want to know if it was in another month... somehthing like that
if(isMoreThanAMonth) {
sharedPreferences.edit().clear().apply()
}
}
Of course, if you want to clear the SharedPreferences even if the user does not open the app you should use a Service. It's more complex and expensive for the OS, so you should try to go for the first one if it fits your requirement.

long installed = context
.getPackageManager()
.getPackageInfo(context.getPackag‌​eName(), 0)
.firstInstallTime
;
public long firstInstallTime
The time at which the app was first installed. Units are as per System.currentTimeMillis().
Now you can compare two date and get months diffrent by using GregorianCalendar
after you get one month different do as you want..clear sharedPrefrence.edit().clear().commit()

One possible way,
1. get the calendar instance.
2. Get maximum day of month.
3. Store in a var1 string in format of dd/mm/yyyy.
4. Get the current date from some calendar object and store in same way from point 3 but in var2.
5. Compare two strings.
6. If match then it will be last day of month and call delete() on your files.
Done.

Related

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

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?
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;
}

How to store current locale date and time in SQLite

..and later retrieve and show them as Strings?
I'm asking the user some input and I want to store both the date (i.e., day, month and year) and the time (i.e., the hour of the day) this input was submitted. Each submission is then saved in my SQlite database, and later retrieved from a RecyclerView.
I'm facing two problems at least. Right now I set up two TEXT fields in the database, FIELD_DATE and FIELD_TIME, where I'd like to store the string representation of date & time, in a format depending on the Android user locale.
From what I've read, the android.text.format.DateFormat should help me. So I set:
java.text.DateFormat dateFormat = DateFormat.getMediumDateFormat(getActivity());
java.text.DateFormat timeFormat = DateFormat.getTimeFormat(getActivity());
Now I think I should call format(Date d) on both objects to get my string, but I don't know where do I get this Date object - don't even know if my two lines are correct. So:
How to get a string representation of current date & time, based on the user defined (at OS level) locale?
That said (asked), I wonder if two fields for date & time are really what I'm looking for. As said, at the end I would like to show a RecyclerView reading the database. In that I will also need to filter out entries based on date, i.e.
Entries referring to last week // last month // All
entries
So I'm also asking:
Is a two-text-fields pattern the right choice to store date & time, given the need to easily filter out entries belonging to, say, last week? Should I better have separate columns for day, month and year?
How to query the database to have only last week rows, given the FIELD_DATE / FIELD_TIME structure (or any other better structure you can suggest)?
I'm quite stuck on these three questions.
Edit: finally came up with how to get the strings I wanted at first, it was as simple as instantiating a new Date object:
Date d = new Date();
String date = DateFormat.getMediumDateFormat(getActivity()).format(d);
String time = DateFormat.getTimeFormat(getActivity()).format(d);
Now I have both the needs to display these strings (which is quite simple, as they are already formatted) and to apply some filter to the db, like entries belonging to last week (which, in turn, would be quite simple with current time in millis since 1970). What to do?
If you want to be able to run complex queries such as find all records from last week, I would recommend storing a timestamp in an integer instead. A timestamp is expressed as the number of milliseconds since the Epoch (Jan 1, 1970). It makes it easy to make queries on exact date and time ranges.
The timestamp is easily found from e.g. System.currentTimeMillis().
The other approach would be to use sqlite's built in date type, but I would personally choose the timestamp approach.
Is there any reason you would want to store it in the current locale's format in the first place? If you are displaying the date to the user you're likely better of formatting the timestamp into a date when displayed, using one of the many date features of Java and android such as java.util.Calendar, java.util.Date, android.text.SimpleDateFormat etc.
As an example, you could run this code to get the timestamp of the start of this month:
Calendar now = Calendar.getInstance();
now.set(Calendar.DAY_OF_MONTH, 1);
now.set(Calendar.HOUR_OF_DAY, 0);
now.set(Calendar.MINUTE, 0);
now.set(Calendar.SECOND, 0);
long startOfThisMonth = now.getTimeInMillis();

Android time management

I am now working with one database record on Android.
It now has one column storing a number and another column storing a time in millisecond.
There should be only one record.
However, the record should be refreshed at 6:00am the next day.
It means that when I want to update the number, I am supposed to check if time now is beyond the refreshing time.
Is there any simple way to achieve this checking?
I am not sure if I have explained this problem clearly. To explain in another way, I want to check if there is one "6 am" between two time stored in millisecond.
Thanks a lot!
public static boolean needRefreshBean(Long milli){
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(milli);
if(cal.get(Calendar.HOUR_OF_DAY)>resettime)
cal.add(Calendar.DAY_OF_YEAR,1);
cal.set(Calendar.HOUR_OF_DAY,resettime);
//cal represents the supposed refresh time
if(cal.getTimeInMillis()<System.currentTimeMillis()){
return true;
}
else
return false;
}
I write a function like this. The input is the updated time stored in the database. I am not sure if this works

GregorianCalendar and SQLite

I'm trying to setup a RPG that will keep track of a virtual time. After some reading GregorianCalendar seems to be the best way to do this but I have some questions and hoping someone with experience could give me some insight.
Here is what I'm trying to do. The game will start in the year 1675 and run for about 30 years. At that point the character will retire if they have survived that long. The character will be able to choose from actions I've preset for them through the coarse of the game. Some actions will be short and take a hour, others may take a week or a month. The real question comes from me using SQLite heavily. I want to save the current time as well as how long an action will take in my database. My first thought when setting this up was, if I want to start the game in Aug 15, 1675 to have my data base with 3 rows, set those fields to 8, 15, 1675. Then also have 2 more columns for the time. Pull these int via cursor and set them with something like
GregorianCalendar time = new GregorianCalendar();
time.set(year, month, date, hour, minute);
I figured I would pull how long an action takes in a similar fashion. Have an int X, and then a string to tell whether this time is in minutes, hours, days etc. Then either add this int to the int pulled from database to add to the calendar directly.
Q: If I add it directly to the calendar how would I pull int values from the calendar to store in database to load at a later time (when the player loads their game)?
Q: If I add it to the int stored in the database and set the calendar with this new int what will happen when I add enough to make the int out of scope for the calendar (Date is set to 31 but I add another day)?
You can convert from the GregorianCalendar object to/from UNIX time for example using getTimeInMillis() setTimeInMillis(). GregorianCalendar also has a roll() method:
Adds the specified amount to the specified field and wraps the value
of the field when it goes beyond the maximum or minimum value for the
current date. Other fields will be adjusted as required to maintain a
consistent date.
I would recommend using Joda Time as a substitute for the (somewhat lacking) standard java date and time utilities. It's much more flexible.
It has functions to do date math, it supports several different calendars (ISO8601, Buddhist, Coptic, Ethiopic, Gregorian, GregorianJulian, Islamic, Julian), has support for intervals, durations and periods. It has built in formatters that let you make your output look like just about anything you wish.
If it were me, I would use Joda and store the date in the native format presented by Joda (I don;t remember what that is right offhand) and then pull it out again and use Joda to do all the date math, as well as having it convert it to whatever calendar you wish to use for display to the user.
Otherwise, it seems to me you'd be re-inventing the wheel.

How to check if timepicker1 time is oldest than timepicker2 time?

i have to select a interval of time.
i have two timepickers on my app, i need to check if timepicker1 selected time is less than timepicker2 selected time. If not, i have to show a toast to told the user the error.
I also need to do this with two datepickers,not with times in that case, but with dates.
please can someone give me some code examples for do this?
You just need to compare the individual components of the date or time in the correct order. For time:
if (time1.getCurrentHour() < time2.getCurrentHour() || (time1.getCurrentHour() == time2.getCurrentHour() && time1.getCurrentMinute() < time1.getCurrentMinute())) {
//time 1 is earlier.
}
You might need to add in a bit of complexity depending on if you are showing 24 hour time or not.
For dates, its the same, just compare first the year then the month then the day.

Categories

Resources