I saw this answer here https://stackoverflow.com/a/24198314/7767733 but could not get it working.
I have a function refreshStuff()
which refresh the values of a Fragment. I call this function when the Fragment is being made, when the user updates the values, and during onResume()
. I also want to force a refresh at midnight, which is relevant when the user is just looking at the screen and not doing anything.
But I am not sure how to set this up in my MyFragment
class. I tried:
public class MyFragment extends Fragment {
...
private AlarmManager alarmMgr;
private PendingIntent alarmIntent;
private Context context;
...
//in onCreate method
context = getActivity();
alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, AlarmReceiver.class);
alarmIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
//midnight I hope
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis()); //do I even need this?
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
AlarmManager.INTERVAL_DAY, alarmIntent);
And if I understand the answer, I have to add this method somewhere:
@Override
public void onReceive(Context context, Intent intent) {
refreshStuff();
}
However I don't have AlarmReceiver
anywhere and I don't know where to put onReceive()
or what I have to define in the Manifest. I also don't know if I have to "turn it off" after I receive it? (do the "alarms" "stack" when they shouldn't?)
Otherwise is this the right way to do this so far?
Edit:
My attempt at implementing CommonsWare's answer:
public class MyFragment extends Fragment implements Runnable, SomeOtherListenersIUse, YetAnotherListenerEtc {
private View viewForDisplayingTotals;
//...rest of implementation omitted for brevity
@Override
public void run() {
refreshValues();
}
@Override
public void onStart() {
super.onStart();
refreshValues();
viewForDisplayingTotals.postDelayed(this, HelperMethods.getMillisecondsTillNextMidnight());
}
@Override
public void onStop() {
super.onStop();
viewForDisplayingTotals.removeCallbacks(this);
}
}
My helper method:
public static long getMillisecondsTillNextMidnight() {
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_MONTH, 1); //add a day first
c.set(Calendar.HOUR_OF_DAY, 0); //then set the other fields to 0
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
return c.getTimeInMillis() - System.currentTimeMillis();
}
Get rid of all the AlarmManager
stuff. That is for when you want to get control in the background at certain times, and in your case, this is only an issue when you are in the foreground.
Step #1: Add implements Runnable
to your MyFragment
definition
Step #2: That will require you to implement the run()
method, and in there, call refreshStuff()
Step #3: In onResume()
(or, better, onStart()
), when you are calling refreshStuff()
, also call postDelayed(this, ...)
on some handy View
, where ...
is the number of milliseconds between now and the next midnight
Step #4: In onPause()
(or, better, onStop()
), call removeCallbacks(this)
on that same View
This will cause your run()
method to be called around midnight, where you will call refreshStuff()
.
//do I even need this?
Yes. Note, though, that your calculation is for the past midnight and ignores the seconds. add()
a day and consider using set()
to zero out the seconds.