I would like to start a task at a specific time. For that I use runnable
and postDelayed
method as follows:
private Runnable mLaunchTask = new Runnable() {
public void run() {
try {
MY TASK
} catch (IllegalStateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
};
In my code I use mLunchTask
as follows:
mHandler = new Handler();
mHandler.postDelayed(mLaunchTask, myDelay*1000);
and myDelay
is computed as follows:
s = DateFormat.format("hh:mm:ss aaa", d.getTime());
cTime = s.toString(); // current Time
ch = Integer.parseInt(cTime.substring(0,2)); // current hour
cm = Integer.parseInt(cTime.substring(3,5)); // current minute
cs = Integer.parseInt(cTime.substring(6,8)); // current second
if (cTime.substring(9,11).equalsIgnoreCase("pm") && (ch<12) ) ch = ch+12;
myDelay=(desiredHour-ch)*3600+(desiredMinute-cm)*60 - cs;
if (myDelay<0) myDelay = 0;
and desiredHour
and desiredMinute
are set by user. The expectation is that MY TASK
starts at desiredHour
and desiredMinute
and 0 seconds.
However "MY TASK starts with a few seconds delay, which looks like is random.
Based on the above code, is there any reason that it does not start at the exact desired time?
Thanks
First of all, your delay calculation is correct, but the "pm" detection doesn't work with other languages. It is much better to use the calendar to get the delay:
Calendar calendar = Calendar.getInstance();
long currentTimestamp = calendar.getTimeInMillis();
calendar.set(Calendar.HOUR_OF_DAY, desiredHour);
calendar.set(Calendar.MINUTE, desiredMinute);
calendar.set(Calendar.SECOND, 0);
long diffTimestamp = calendar.getTimeInMillis() - currentTimestamp;
long myDelay = (diffTimestamp < 0 ? 0 : diffTimestamp);
Now you have the delay in milli secs and can start the handler:
new Handler().postDelayed(mLaunchTask, myDelay);
In my test the following runnable logs at the desired time with no delay.
private Runnable mLaunchTask = new Runnable() {
public void run() {
Calendar calendar = Calendar.getInstance();
Log.d("test", "started at "
+ calendar.get(Calendar.HOUR_OF_DAY) + " "
+ calendar.get(Calendar.MINUTE) + " "
+ calendar.get(Calendar.SECOND)
);
}
};
Maybe your started task needs some seconds to be loaded?
Could the AlarmManager be an alternative?
Based on my experience and reading of the documentation, postDelayed is based on uptime, not real time. If the phone goes into deep sleep, it can cause real time to pass without uptime incrementing. That means your task will start later than desired.
The Handler really seems to be designed for updating the GUI in an active activity, not scheduling tasks far in the future. As scessor said, AlarmManager is probably your best bet.
The Naliba's answer is not completely correct.
Based on documentation that can be seen here it can be seen that this class is specifically used for running tasks in the future.
"There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own. "
There is no reference about the behavior of the application when the system enters in sleep mode and this issue should be tested before posting additional information.
来源:https://stackoverflow.com/questions/6728861/running-a-task-at-a-specific-time-using-postdelayed