0

I have a problem with scheduleAtFixedRate. It will only called once and does not repeat. what is wrong?

public class TimerService extends Service {
static final int UPDATE_INTERVAL=3000;
private Timer timer = new Timer();
private Date date;

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    repeatJob();
    //Here we want this service to continue running until it is explicitly stopped, so return sticky
    return START_STICKY;
}

private void repeatJob() {
    timer.scheduleAtFixedRate(new TimerTask() {
        @Override
        public void run() {
            Looper.prepare();

            date = new Date();
            displayToast(date.toString());
            Log.d("repeat", new Date().toString());

            Looper.loop();
        }
    }, 0, UPDATE_INTERVAL);
}

private void displayToast(String text) {
    Toast.makeText(this, text, Toast.LENGTH_LONG).show();
}

}

I call the service in fragment activity:

getActivity().startService(new Intent(getActivity().getApplicationContext(), TimerService.class));

How can I get the current value of date (and maybe more values in future) from service to fragment activity?

Thank you!

honiahaka10
  • 772
  • 4
  • 9
  • 29

2 Answers2

1

You are doing so many odd things here, I'm not sure what exactly causes the problem, but I'll tell you how this would be done normally:

You should use AlarmManager to schedule the service for repeated execution, and get rid of the Timer. The Timer only works if your process is alive, while the AlarmManager will remember pending intents even if your app's process is not running (and in this case it will start it). It is also more memory and battery efficient, as it is a centralized system that manages programmed tasks for all apps, not only yours.

The service should not re-schedule itself, just do the task it needs to do. Be aware they run in the Main Thread, so you'd need to create a worker thread. Consider using an IntentService as it gives you this already done. To pass back the result to the activity, your service can send an intent to the activity containing the data in the extras. You could also broadcast the result and handle it in a broadcast receiver in the activity, or you can also bind to the service and register a callback.

Remove the Looper lines, you don't need this after getting rid of the timer.

Finally, you seem to be a bit confused about what the START_STICKY flag does. It does not make the service to "continue running until it is explicitly stopped". There's no way to guarantee a service will be running indefinitely in Android. What this flag does is to tell the system that, in case it gets short of memory and it kills the service, once it recovers it should try to re-create the service, but without redelivering pending intents. More info here.

Mister Smith
  • 27,417
  • 21
  • 110
  • 193
  • The comment before START_STICKY is just copied from the original code of my professor. First QUestion for the IntentService: I created the Intent in the Service like this: Intent retIntent = new Intent(TimerService.this, MainActivity.class); retIntent.putExtra("date", date.toString()); How do I get the date in MainActivity? Question for the AlarmManager: I tried to use AlarmManager in the onHandleIntent of the service, but the app will crash I can not write evrything because it would be too long for comment... :/ – honiahaka10 May 23 '14 at 14:32
  • The intent will be passed as parameter to the activity's `onCreate` (if the activity needs to be recreated) or to the `onNewIntent` method (if the activity was already alive). Then you can call `Intent.getStringExtra` to retrieve the string. As for the second question, you might open a second question if needed, remember to post the stack trace. – Mister Smith May 26 '14 at 15:27
0

Ok. I just faced the same problem and the weird thing is when i remove the Looper.prepare & Looper.loop, it actually executes with the given interval time BUT the execution isn't successful bcoz it says it needs Looper.loop So far I cant remove it since its needed, but when its there it makes the task execute once .. plus im no android expert. let me know if u got any updates on that.