11

I'm trying to build an Android app which will repeatedly run some process every 10 mins. As I found out Handlers are more reliable than timers or scheduling. So I'm going to develop my app using the Handlers using the given below codes.

I'm little bit concerned that the below codes will create separate Handlers at each time I start the app and keep them running parallel, may be since I'm creating the Handler on onCreate.

So what is the best way to keep only a single Handler runs in background at a time?

private Handler handler;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    handler = new Handler(); // new handler
    handler.postDelayed(runnable, 1000*60*10); // 10 mins int.
    setContentView(R.layout.activity_pro__sms);
} 

private Runnable runnable = new Runnable() {
    @Override
    public void run() {
        /* my set of codes for repeated work */
        foobar();
        handler.postDelayed(this, 1000*60*10); // reschedule the handler
    }
};
Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
kuma DK
  • 1,812
  • 1
  • 18
  • 36
  • Just wondering: what's the context of your 'repeated work'? Or perhaps better said: what kind of app is it? It may be a very generous assumption to think users will actively use your app for 10+ minutes at a time (unless it's like a game or so, hence my question). Using a `Handler` while your app is *not* in the foreground, could not the right course of action. – MH. Oct 04 '14 at 08:05
  • Why not use a service? – Andrew Kirkegaard Oct 04 '14 at 17:22
  • I don't need to miss the task by running even while in sleep mode. Can services be active while even in idle(sleep) mode? Or do i need to have a wake lock. What about resource usage by services in compared to AlarmManager (now I'm trying the things with alarm manager) – kuma DK Oct 04 '14 at 17:30

3 Answers3

7

You can extend Application class and do your work in it.

public class App extends Application {

    private Handler handler;

    @Override
    protected void onCreate() {
        super.onCreate();
        handler = new Handler(); // new handler
        handler.postDelayed(runnable, 1000*60*10); // 10 mins int.
        setContentView(R.layout.activity_pro__sms);
    } 

    private Runnable runnable = new Runnable() {
        @Override
        public void run() {
            /* my set of codes for repeated work */
            foobar();
            handler.postDelayed(this, 1000*60*10); // reschedule the handler
        }
    };
}

And declare your class in manifest:

<application android:name=".App">

Edited

But it will work only if your app is running, otherwise you can use AlarmManager.

Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
Bracadabra
  • 3,609
  • 3
  • 26
  • 46
  • Thanks. I'll give it a try and reply u back within minutes. – kuma DK Oct 04 '14 at 07:53
  • actually what i want is to prevent multiple handlers being created. there should be a way, in android developers site they says handler is the most suitable way. – kuma DK Oct 04 '14 at 08:10
  • 2
    What Vang gave you will create only one handler, and repeat the process based on the time passed. Notice he's extending the Application class, which is only called once, that is, when your application is created (when you start the application). The handler will stop working if you completely destroy the application, otherwise, only one will run at a time. If you're looking for a handler to run constantly, use the AlarmManager as mentioned above. – NightwareSystems Oct 04 '14 at 08:12
  • Thanks Vang and NightwareSystems for your comments. I've figured out that I should use AlarmManager not the Handler class. What Vang is posted is perfect with Handlers but i needed is AlarmManager as you have suggested. Thanks you again for your ideas... – kuma DK Oct 04 '14 at 15:57
5

I decided to answer my own question since I've found out how to do it right way. The Android way. First of all what I was trying to do and posted in the question is a wrong approach to my requirement. Now I'm posting this so someone else will not do it wrong way but the following way.

Android has few options for timing.

  1. Timer-task -> runs while application is alive. best for short term timing. Resource usage is higher.

  2. Handler -> runs while application is alive. But not suitable to used as a scheduler. (this is what I've asked and it's not the correct way to do that). Handlers are the best way to do something repeatedly till the app is killed.

  3. Alarm-manager -> The best way to schedule something to happen in future even if the app is killed. (this is what I should apply for my app).

This is what I figured out. Correct me if I'm wrong.

Massimiliano Kraus
  • 3,638
  • 5
  • 27
  • 47
kuma DK
  • 1,812
  • 1
  • 18
  • 36
1

first define an utility class

public abstract class HandlerPeriodRunnable implements Runnable {

    private Handler periodHandler;
    private int msPeriod;

    public HandlerPeriodRunnable(Handler periodHandler, int msPeriod) {
        this.periodHandler = periodHandler;
        this.msPeriod = msPeriod;
    }

    @Override
    public void run() {
        periodRun();
        if (msPeriod > 0) {
            periodHandler.postDelayed(this, msPeriod);
        }
    }

    abstract public void periodRun();
}

then use it

final Handler mUIHandler = new Handler();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mUIHandler.postDelayed(new HandlerPeriodRunnable(mUIHandler, 1000) {
        @Override
        public void periodRun() {

        }
    }, 2000);
}
Yessy
  • 1,172
  • 1
  • 8
  • 13