For my latest project I need to process some data and send it to a remote server. This was a perfect use case for an IntentService. I can just bundle my data as an extra, and start my service.

My biggest issue with an IntentService is that if it fails to start, I have essentially no way of knowing it failed. So I wanted a way to guarantee (or at least a best effort) that my intent starts up and processes my data.

First an intro to the IntentService

An intent service is a special subclass of the Service class. With a standard service, you generally override the onStartCommand(Intent, int, int) method. More importantly, all methods in the standard Service class run on the main thread.

This is not ideal if you want to perform any calculations, disk access, or network access from within your service without managing your own threads.

With an IntentService you get a new method to override called onHandleIntent(Intent intent) that is called in a dedicated background thread.

Starting an Intent Service

To start an intent service and pass your data, you can create an intent, add extras, and start the service.

With Intent redelivery enabled, Android will keep attempting to deliver your intent to your service until onHandleIntent(Intent) returns without crashing.

So the app is killed or crashes, when is the Intent redelivered?

Android redelivers intents to your service using exponential backoff timeouts. This means each time the intent is not delivered, the delay before trying again goes up exponentially. Here is a sample log output.

W/ActivityManager: Scheduling restart of crashed service .RedeliveryService in 16896ms
W/ActivityManager: Scheduling restart of crashed service .RedeliveryService in 67584ms
W/ActivityManager: Scheduling restart of crashed service .RedeliveryService in 270336ms

This also works for crashes, but the interesting part is, the intent will no longer be delivered after your app crashes 2 times. I couldn’t find this documented anywhere, but after testing on API 19 this is the case.

It doesn’t matter how many attempts at redelivering have been made, it just keeps a running count of crashes and stops trying after 2.

Redelivery Overview

The system will keep redelivering (with an exponential delay) when the app is killed. The app will redeliver after 1 crash (with an exponential delay). Once the service crashes twice, redelivery stops.

For example you send your intent to your service

The app is killed by the system. Android redelivers intent

The service crashes Android redelivers intent

The app is killed by the system again Android redelivers intent

The app is killed by the user Android redelivers intent

The service crashes for a second time Android gives up

Summary

The intent service has a pretty robust and well designed redelivery system. The biggest issue is that there is next to no documentation on the actual behavior of redelivery.