androidperformanceandroid-activityandroid-lifecyclesystem.exit

self destructing an android app after certain amount of time


i currently work on an app that needs a lot of battery in order to support background gps tracking. my experience shows that people just forget about the app runnning in the background when they dont really need the tracking anymore. therefore i setup some code that should close the application after 4 hours.

public class SelfDestructor {

    private static SelfDestructor instance;

    private final long IDLE_TIME_UNTIL_AUTO_DESTRUCT = 4 * 60 * 60 * 1000; // 4 hours

    private Handler handler;

    private Runnable closeApp = new Runnable() {
        @Override
        public void run() {
            System.exit(0);
        }
    };

    public static SelfDestructor getInstance() {
        if (SelfDestructor.instance == null) {
            SelfDestructor.instance = new SelfDestructor();
        }
        return SelfDestructor.instance;
    }

    public void keepAlive() {
        if (handler == null) {
            handler = new Handler();
        }
        handler.removeCallbacks(closeApp);
        handler.postDelayed(closeApp, IDLE_TIME_UNTIL_AUTO_DESTRUCT);
    }
}

now in my main activity i call keepAlive().

@Override
protected void onResume() {
    super.onResume();
    SelfDestructor.getInstance().keepAlive();
}

@Override
protected void onStart() {
    super.onStart();
    SelfDestructor.getInstance().keepAlive();
}

now if i set the time to an hours or so and debug the that functionality everything works fine. if i set the time to 4 hours the System.exit(0); is never called. i am assuming the app thread with the close callback is just put on hold by the android system after a while and therefore will not be executed anymore while gps will continue to run. any ideas how to properly get this to work?


Solution

  • handler and postDelayed are not suited for long timers. At most they should be used within a few seconds and personally I think I never used one for anything more than 2 seconds.

    Said all that, Android have an appropriate class for "stuff that should happen after a long time", it's called AlarmManager: http://developer.android.com/reference/android/app/AlarmManager.html

    you can get the references to the system service AlarmManager by calling Context.getSystemService(Context.ALARM_SERVICE)

    and then set it by calling am.set(AlarmManager.ELAPSED_REALTIME, IDLE_TIME_UNTIL_AUTO_DESTRUCT, operation)

    the operation is a PendingIntent to a BroadcastReceiver that you register in the AndroidManifest.xml via the <receiver> tag. Then you do the close application code inside this broadcast receiver.

    Also I should add that it's NEVER good to call System.exit(0);, as this just destroy the VM without much of a warning. It's a better, more organised/structured shut down if you pass a command to the Service that is holding the GPS (I believe you're running a service), then this service will cancel the GPS request, and call stopSelf();