0

i have a problem using TimerTask in android. The situation is this one:

I have a class extending AsyncTask, cal it MyAsyncTask, and i have a static method in another class, call it SchedulerClass.

SchedulerClass has this method

TimerTask myTimerTask;
public static boolean scheduleMyJob() {
        try {
            Log.i(LOG_TAG,"entered in scheduleMyJob function");

            MyAsyncTask task = new MyAsyncTask ();
            myTimerTask = new TimerTask() {

                @Override
                public void run() {
                    try {
                        _task .execute("");
                    } catch (Exception e) {
                        Log.e(LOG_TAG, "error executing task");
                    }
                }
            };
            Timer t = new Timer();
            t.schedule(myTimerTask , 10000);
            return true;

        } catch (Exception e) {
            Log.e(LOG_TAG, "error scheduling task");
            return false;
        }
    }

and MyAsyncTask is something like this

public class MyAsyncTask extends AsyncTask<String, Integer, String> {


    @Override
    protected String doInBackground(String... params) {
             Log.i(LOG_TAG,"entered in MyAsyncTask.doInBackground method");

             //DO MY STUFF

             return "result";
        }

        @Override
    protected void onPostExecute(String result) {
           SchedulerClass.scheduleMyJob();
        }
}

This approach works fine most of the time, but sometime myTimerTask is scheduled after much more than 10 seconds: i can read the log "entered in scheduleMyJob function"but the log "entered in MyAsyncTask.doInBackground method" is written after much more than 10 seconds (which is the time used for scheduling). When I say "much more" I mean even minutes.

what's wrong? I need an accurate timing system, I can tolerate a few seconds but no minutes.

Moreover i need this scheduling being active even if the device is in standby

Thanks for any help

Apperside
  • 3,542
  • 2
  • 38
  • 65
  • "Moreover i need this scheduling being active even if the device is in standby" -- that means you can never allow the device to go into "standby". Unless this will only be going on for a *very* short time and *completely* under user control, users will be unhappy with the battery drain. – CommonsWare May 13 '13 at 12:30
  • this application is used in a business enviroment, the users know about these continuos updates and, above all, they need these updates – Apperside May 13 '13 at 12:38
  • Their devices will be largely unusable, unless they are very frequently plugged in. Mobile device CPUs are not meant to run continuously. – CommonsWare May 13 '13 at 12:44
  • in the real enviroment these updates will run every 10 minutes or more, in my tests I'm using 10 seconds – Apperside May 13 '13 at 12:53
  • anyway, what do you suggest if these are my requirements? – Apperside May 13 '13 at 12:57

1 Answers1

0

in the real enviroment these updates will run every 10 minutes or more, in my tests I'm using 10 seconds

That's much more sensible.

what do you suggest if these are my requirements?

Delete all of your existing code.

Then, set up AlarmManager ELAPSED_REALTIME_WAKEUP events, tied to a BroadcastReceiver and either my WakefulIntentService or your own IntentService/WakeLock logic. You need this combination in order to satisfy your "scheduling being active even if the device is in standby" requirement.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • why are you suggesting ELAPSED_REALTIME_WAKEUP? isn't it used for event tied to system boot time? The logic of my updates is this: the app starts, schedule the update after ten minutes, and at the end schedule the updates again after ten minutes. in order to implement such logic, isn't better RTC_WAKEUP? Other question: is the alarm manager more reliable than Timer? – Apperside May 13 '13 at 13:29
  • @SimonVeloper: "why are you suggesting ELAPSED_REALTIME_WAKEUP?" -- only use `RTC`/`RTC_WAKEUP` when you need the alarms to be tied to somebody's calendar (e.g., must alert the user about their dentist appointment at 10:00 next Tuesday). Beyond that, `ELAPSED_REALTIME`/`ELAPSED_REALTIME_WAKEUP` is more resilient. "isn't better RTC_WAKEUP?" -- no. "is the alarm manager more reliable than Timer?" -- your problem with `Timer`, if I had to guess, was that the device was entering "standby", with the CPU powered down. `AlarmManager` works with "standby", `Timer` does not. – CommonsWare May 13 '13 at 13:52
  • I can sweare to have seen the timer triggered even after pressing home key (paused the app) and and pressing on/off button (put in sleep mode the phone). how is this possibile? – Apperside May 13 '13 at 14:37
  • @SimonVeloper: Other things will occasionally power on the device to do work, using `AlarmManager` and a `_WAKEUP` alarm. That, in turn, has a chance to trigger your code, albeit perhaps very late. – CommonsWare May 13 '13 at 17:52
  • ok, thanks a lot for the help. I have some more little question: in the alarm's receiver, need I to acquire wake lock (obviously declaring the permission in the manifest) in order to get the update triggered when the phone is in sleep mode? Need I to unregister the scheduled action when the user quits from the app (the update must run only while the app is running)? in the AlarmManager's page i read that AlarmManager is intended for the cases when you want to run the code even if your application is not currently running, and that for other cases Handler is better? should I think about it? tks – Apperside May 13 '13 at 18:51
  • @SimonVeloper: "need I to acquire wake lock..." -- yes. "Need I to unregister the scheduled action when the user quits from the app..." -- since there is no concept in Android of "the app is running", you have a fundamental misunderstanding of how Android apps work. "should I think about it?" -- no. – CommonsWare May 13 '13 at 19:06
  • I well know there is no concept in Android of "the app is running", but i said that because I have a quit button which pratically kills the app (after calling finish() method for the last activity in the stack). What happen if I have scheduled a PendingIntent and quit from the app in that way? Is the PendingIntent fired anyway? – Apperside May 13 '13 at 19:18
  • @SimonVeloper: "What happen if I have scheduled a PendingIntent and quit from the app in that way?" -- if by "scheduled a PendingIntent" you mean via `AlarmManager`, it will keep going until the next reboot or until you explicitly cancel it. However, there are any number of ways the user can leave your app (e.g., BACK, HOME, opening another app from the recent-apps list, swiping your app off the recent-apps list, tapping on a notification). This is why having a "quit button" is an anti-pattern: it makes you, the developer, think that you are in control when you are not. – CommonsWare May 13 '13 at 19:21