sdabet
sdabet

Reputation: 18670

Is it safe to start a new thread in a BroadcastReceiver?

I need to perform a network operation in a BroadcastReceiver.

So far I achieve it by starting a new thread:

@Override
public void onReceive(Context context, Intent intent) {
    new Thread(new Runnable() {
        public void run() {
            // network stuff...
        }
    }).start();
}

Is there any risk that the process will be killed before the thread is done?

Is it better to use an IntentService instead? Any other better approach?

Upvotes: 10

Views: 3341

Answers (3)

einUsername
einUsername

Reputation: 1619

Here is some practical information from my tests:

  • The onResume lasts for 10 seconds.
  • The Thread itself lasts far longer. About 7 minutes on an idle device.
  • Filling about 450MB of RAM (on a 4GB device) will stop the thread and garbage collect everything.
  • Reliability is worse if the BroadcastRecevier is triggered while the device is in sleep-mode (by an AlarmManager). Most of the time it runs fine but sometimes it runs hours later when the phone get's unlocked and sometimes it doesn't run at all. (I used a wake lock too but I don't think it made much of a difference.)

This could be worth trying in some cases because from my experience the android specific threading solutions are not very reliable as well. Maybe for something like a widget button that fetches the latest weather forecast...

Upvotes: 0

Waves
Waves

Reputation: 1003

It isn't the best idea. The life-cycle of a BroadcastReceiver lasts as long as it takes to finish calling onReceive(), after that it's destroyed. If you were to start running a new thread, there's a chance the BroadcastReceiver would be killed before the thread completes, which would wind up in some unexpected behaviour.

The better option would be to start a background service, like you said.

Upvotes: 1

CommonsWare
CommonsWare

Reputation: 1007099

Is there any risk that the process will be killed before the thread is done?

If this receiver is registered via the manifest, yes.

If this receiver is registered via registerReceiver(), the lifetime of your process will be determined by other running components.

Is it better to use an IntentService instead?

If that work will be over a few milliseconds, IMHO, yes, probably in concert with WakefulBroadcastReceiver.

Any other better approach?

There is a goAsync() option on BroadcastReceiver that gives you a window of time to do work in another thread before triggering an ANR. I avoid this, because it is poorly documented. For example, it does not directly address your question: what is the process importance while this background thread is doing its work? Does this keep the device awake long enough for our work to get done? And so on. I'll use an IntentService or some other form of Service, where I have better understanding of the contract.

Upvotes: 10

Related Questions