1

In my app, I would like to offer an action, which shall be executed in background regularly. So I use the AlarmManager, which starts an IntentService.

The tricky part is, that this background action needs Internet connection. So I tried using a WakeLock which didn't seem to enforce a connection, when the device was locked.

Then I thought about registering a BroadcastReceiver to listen for "android.net.conn.CONNECTIVITY_CHANGE" when the service starts and immediately unregistering it, as soon as the desired broadcast is received.

My code looks something like this:

public class BackgroundService extends IntentService {
    private static final IntentFilter filter =
        new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
    private static NetworkStateChangedReceiver receiver =
        new NetworkStateChangedReceiver();

    protected void onHandleIntent(Intent intent) {
        registerReceiver(receiver, filter);
    }
}

My question is now: Will this receiver be destroyed, as soon as the service stops (as it has nothing to do, as long as no connection is available)? And therefore, how can I realize a service, that delays it's work until a network connection is availalbe?

Thanks.

Kirill Rakhman
  • 42,195
  • 18
  • 124
  • 148

1 Answers1

1

Will this receiver be destroyed, as soon as the service stops (as it has nothing to do, as long as no connection is available)?

Yes. It will live for a few microseconds.

And therefore, how can I realize a service, that delays it's work until a network connection is availalbe?

Use ConnectivityManager and getActiveNetworkInfo(), see if there's a connection, and if not, just exit onHandleIntent() and wait for the next alarm.

Or, register your CONNECTIVITY_ACTION receiver in the manifest and use it to schedule and cancel your alarms, so the alarms are only active while there's a connection.

There are various other strategies, but those two should give you a starting point.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • So the best I can do, is start the task over and over until the connection is established? – Kirill Rakhman Sep 10 '11 at 21:17
  • @cypressious: That is one approach. I outlined two, one of which would not fit that description. – CommonsWare Sep 10 '11 at 21:24
  • I see. Your second suggestion is to register a permanent BroadcastReceiver. In my case, the task shall be executed 1-2 times a day. Isn't it bad style, to process broadcasts every 5 minutes, ignoring 95% of them? – Kirill Rakhman Sep 10 '11 at 21:27
  • @cypressious: "Isn't it bad style, to process broadcasts every 5 minutes" -- and your proof that `CONNECTIVITY_ACTION` happens every 5 minutes is, what, exactly? "In my case, the task shall be executed 1-2 times a day" -- which, of course, you decided not to mention in your question. In that case, when the alarm event occurs, if there is no connectivity, I'd enable the `CONNECTIVITY_ACTION` manifest-registered receiver using `PackageManager`. If the `CONNECTIVITY_ACTION` occurs and you now have connectivity, do the work and disable the `CONNECTIVITY_ACTION` receiver. – CommonsWare Sep 10 '11 at 21:33
  • "and your proof that CONNECTIVITY_ACTION happens every 5 minutes is, what, exactly?" Well, of course this is speculation, but I assume that the connection is disconnected quite often, e.g. for saving power during locked state. Anyway, I'm sorry for not mentioning the expected frequency of the task and your suggestion sound very interesting. I guess your answer in http://stackoverflow.com/questions/5624470/enable-and-disable-a-broadcast-receiver is the way to go? – Kirill Rakhman Sep 10 '11 at 21:46
  • @cypressious: "I assume that the connection is disconnected quite often, e.g. for saving power during locked state" -- most users are not pressing the power button every 5 minutes, though. It will only get broadcast when the device flips from WiFi to mobile data or back, or loses all connectivity. Still, it will be more frequent than your twice-a-day event, so your intention is good. "I guess your answer... is the way to go?" -- yes, that is how to enable and disable a manifest-registered receiver. You would probably have yours disabled to start in the manifest, enabled only when needed. – CommonsWare Sep 10 '11 at 21:53
  • I implemented your suggestion as you described it before going to bed and scheduled the task to happen 4 hours later. Additionaly a WakeLock is aquired before starting the task. Unfortunately it didn't work out. The service was triggered (indicated by a notification), which means, that the folowing method returned true: `ConnectivityManager cm = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE); return cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnectedOrConnecting();` But the progress remained stuck at 0%, so I'm a little bit clueless. – Kirill Rakhman Sep 11 '11 at 10:57
  • @cypressious: Make sure you are using my `WakefulIntentService` or are otherwise holding a `WakeLock`, otherwise the device will fall back asleep while you are doing your work. Beyond that, I have no advice given the available information. – CommonsWare Sep 11 '11 at 12:27
  • A WakeLock is used but it's still not working. My main problem is, that I'm not able to debug my app propperly because I can't emulate the locked state. Is there any possibility to do so? – Kirill Rakhman Sep 12 '11 at 12:37
  • @cypressious: You are welcome to play around with the power commands in the telnet interface to the emulator, but personally I would not trust the results. – CommonsWare Sep 12 '11 at 12:47