18

I have a service that I am wanting to execute a task every minute in the background. It does not need to execute the task whenever the phone is asleep, only when the user is actively using it. I am trying to do this with an IntentService which is set up as follows:

public class CounterService extends IntentService{

    public CounterService() {
        super("CounterService");
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
       return super.onStartCommand(intent,flags,startId);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Toast.makeText(this, "onhandleintent", Toast.LENGTH_SHORT).show();
        while(true)
        {
            //one minute is 60*1000
            try {
                Thread.sleep(5 * 1000);
                Toast.makeText(getApplicationContext(), "getting app count", Toast.LENGTH_LONG).show();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

Right now to get the functionality working I simply want it to display a toast every 5 seconds, I will change it to one minute later. If I have the while(true) commented out, then the "onhandleintent" message is displayed. However if I have the following code run, neither of the Toasts display. How can I fix this?

AggieDev
  • 5,015
  • 9
  • 26
  • 48
  • Consider the use of PendingIntent and AlarmManager instead of a while loop. See the docs for more info. Here is a [SO post](http://stackoverflow.com/questions/3052149/using-alarmmanager-to-start-a-service-at-specific-time) that shows an example. – Vino Feb 23 '14 at 21:20

3 Answers3

22

This will send an intent to your service every minute without using any processor time in your activity in between

  Intent myIntent = new Intent(context, MyServiceReceiver.class);
  PendingIntent pendingIntent = PendingIntent.getBroadcast(context,  0, myIntent, 0);

  AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
  Calendar calendar = Calendar.getInstance();
  calendar.setTimeInMillis(System.currentTimeMillis());
  calendar.add(Calendar.SECOND, 60); // first time
  long frequency= 60 * 1000; // in ms 
  alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), frequency, pendingIntent);           

Adjust MyServiceReceiver.class to match your target service or activity. The documentation provides more details to fine-tune your calls like whether you want exact timing, execution at a specific time of the day ...

Vince
  • 1,570
  • 3
  • 27
  • 48
Android Newbie
  • 711
  • 3
  • 9
  • 1
    It should be PendingIntent.getService instead of PendingIntent.getBroadcast in order to run a service. – Vistritium Jan 04 '17 at 23:01
  • well i am using a intent service and want to run it at every specific interval. it gets runs only until app is in background.what should be the solution – atish naik Dec 11 '18 at 16:10
6

You need to exit the main thread to avoid risking a ANR.

Instead add a Handler

Handler mHandler = new Handler();

...

@Override
protected void onHandleIntent(Intent intent) {
    Toast.makeText(this, "onhandleintent", Toast.LENGTH_SHORT).show();
    mHandler.postDelayed( ToastRunnable, 5000);
    //while(true)
    //{

        //one minute is 60*1000
        //try {
        //    Thread.sleep(5 * 1000);
        //    Toast.makeText(getApplicationContext(), "getting app count",          
        //Toast.LENGTH_LONG).show();
        //} catch (InterruptedException e) {
            // TODO Auto-generated catch block
        //    e.printStackTrace();
        //}
    //}
}
final Runnable ToastRunnable = new Runnable(){
    public void run(){
         Toast.makeText(getApplicationContext(), "getting app count",          
               Toast.LENGTH_LONG).show();
         mHandler.postDelayed( ToastRunnable, 5000);
    }
}
jeremyvillalobos
  • 1,795
  • 2
  • 19
  • 39
2

Do it like this

    private void ping() {
    try {
        //Your code here or call a method
    } catch (Exception e) {
        Log.e("Error", "In onStartCommand");
        e.printStackTrace();
    }
      scheduleNext();
    }

    private void scheduleNext() {
      mHandler.postDelayed(new Runnable() {
        public void run() { ping(); }
      }, 60000);
    }

    public int onStartCommand(Intent intent, int x, int y) {
      mHandler = new android.os.Handler();
      ping();
      return START_STICKY;
    }
Prashant Yadav
  • 531
  • 2
  • 9
  • 25