Question

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

Was it helpful?

Solution

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?

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top