5

I have a service that runs upon boot completion. This service requires internet connectivity. What's the best practice for waiting for the device to connect to the internet? Mobile of wifi doesn't really matter.

My current solution involves a while loop that just checks ConnectivityManager until one of the networks becomes available, but this feels vulgar.

Is there a better way to do this?

Lunchbox
  • 2,136
  • 7
  • 29
  • 40

2 Answers2

2

but this feels vulgar

Indeed :D

  1. Your receiver wakes your wakeful intent service (probably a simple intent service would do, as the phone does not sleep while booting AFAIK)
  2. service registers a receiver for connectivity
  3. service waits on a CountDownLatch
  4. the receiver wakes the service up when the wifi is connected

Skeleton code : https://stackoverflow.com/a/19968708/281545 - your case is simpler as you do not have to wake the wifi, hold wifi locks etc. Otherwise (including the case this takes long and radios/CPU sleep - in which case a simple intent service won't do) between 2 and 3 you would need to :

2a. service acquires a wifi lock
2b. service calls reconnect(), reassociate() and whatever is needed (this may be device specific)

Community
  • 1
  • 1
Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
1

You could use a BroadcastReceiver:

private class ConnectionMonitor extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION))
            return;
        boolean noConnectivity = intent.getBooleanExtra(
            ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
        NetworkInfo aNetworkInfo = (NetworkInfo) intent
            .getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
        if (!noConnectivity) {
            if ((aNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE)
                || (aNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI)) {
                // start your service stuff here
            }
        } else {
            if ((aNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE)
                || (aNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI)) {
                // stop your service stuff here
            }
        }
    }
}

Then, you instantiate somewhere in your code:

ConnectionMonitor connectionMonitor = new ConnectionMonitor();
registerReceiver(connectionMonitor, intentFilter);

Note: this code comes from Detect 3G or Wifi Network restoration

Community
  • 1
  • 1
znat
  • 13,144
  • 17
  • 71
  • 106
  • Wouldn't that run the service every time a connection was established? I only need to run the service once at start up and need to wait until the connection is available. It is already in a BroadcastReceiver that listens for `android.intent.action.BOOT_COMPLETED`. – Lunchbox Feb 12 '12 at 16:34
  • Please confirm my understanding: you need your service to start as soon as a connection is detected? If yes, then you could make this class public (in its own file), put a startService (some context needs to be passed) method at the right place, and instantiate and register the BR in your starting activity. (don't forget to unregister when your service is started) – znat Feb 12 '12 at 16:39
  • 1
    @Lunchbox: You indicated that you are starting a service from your `BOOT_COMPLETED` receiver. The code in this answer would go in that service, if you determine that there is not already an Internet connection. You would also want some sort of timeout mechanism, in case the user simply does not have Internet access, or you have exceeded your bandwidth quota on Android 4.0+. – CommonsWare Feb 12 '12 at 17:03