Tsar Bomba
Tsar Bomba

Reputation: 1106

IntentService, PendingIntent, and AlarmManager: Cannot keep process running indefinitely?

I've got a pretty simple app that runs two services in the background, using IntentService with AlarmManager. One is a "messaging" service that sends a JSON request and parses the response, the other polls for location from a LocationManager. The requirement here is that they run on an interval, indefinitely, until manually stopped by the user, with a button - even if the device's screen hasn't been turned on for days. The services must never stop. Battery life is not a concern.

My minimum-supported API is 4.1 and I'm testing on 4.1, 4.2, and 4.4 devices. On my Nexus 7 and GPad, 4.4.4 and 4.4.2, respectively, the services will run indefinitely and work as expected. On a Galaxy Tab 3 running 4.2, the device seemed to go to sleep after 8 hrs. or so of inactivity, and would then quit reporting location and polling. The 4.1 devices seem to do the same.

With that hunch, I added this to the messaging service to manually wake the CPU. This one runs every 60 sec. so I had hoped it would prevent the devices from ever going to sleep.

@Override
protected void onHandleIntent(Intent intent)
{                       
    PowerManager pm = (PowerManager)getSystemService(Context.POWER_SERVICE);
    PowerManager.WakeLock wl = pm.newWakeLock(
            PowerManager.PARTIAL_WAKE_LOCK, 
            "com.service.MESSAGE_SERVICE_WAKE_LOCK");

    wl.acquire();

    //poll for messages via JSON    

    wl.release();               
}

Setting the AlarmManager like so (pi = PendingIntent...passing in the IntentService class):

alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), pollInterval, pi);

This appeared to fix things for my own testing, and the devices are consistently reporting location for me on 4.4 and 4.2. However, the 4.1 testers have reported that it still goes to sleep on them after about 8 hrs. I also tested it on a friend's Galaxy S5 (4.4.2) and it quit reporting location after a few hours.

This is my first app and this part has been especially frustrating. Am I doing something wrong? Any idea why these services might stop running? Happy to provide more code if that helps...thought I'd start with this, at least.

Upvotes: 0

Views: 1215

Answers (2)

android developer
android developer

Reputation: 116392

If you wish for a service to "always" run, you shouldn't make is a background service.

Make it a foreground service instead:

A foreground service is a service that's considered to be something the user is actively aware of and thus not a candidate for the system to kill when low on memory.

In order to try out how long your service can run when the OS has low RAM, you can try this sample I've made (which I've posted here, and uses this library I've made), which uses more and more RAM (real RAM, not of the heap). It causes the OS to kill other processes and eventually kill the process of the sample itself.

If you just want your services to run every X hours/minutes, you don't need this at all, and what you've found seems ok.

Upvotes: 1

Larry Schiefer
Larry Schiefer

Reputation: 15775

Alarms which use PendingIntent for a Service are not guaranteed to keep the device awake long enough for the Service to be started or resumed. In the case of an IntentService, the service automatically dies once it has processed all queued Intent objects. You'll need to use a PendingIntent for a BroadcastReceiver which takes a WakeLock and starts your Service. Your Service can then release the wakelock when it is done with its work, allowing the device to go back to sleep.

Upvotes: 3

Related Questions