0

I am currently using a background IntentService in my Android App to connect to my server to fetch some data and update the App only if connection is available. If the device is connected to mobile network data or a authenticated wifi connection or open wifi connection it works perfectly.

The problem occurs when the device does not have access to Mobile Data Network and is connected to a Wifi source that requires authentication and the connection is not authenticated yet, the service force closes since it is unable to transfer any data through the unauthenticated connection.

My check to the entry point to connect to the server and do the background task is the check below.

ConnectivityManager conMgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
        if((conMgr.getActiveNetworkInfo() != null &&
                conMgr.getActiveNetworkInfo().isAvailable() &&
                conMgr.getActiveNetworkInfo().isConnected()) || WifiConnected() == true){

//do background processing }

The WifiConnected() method looks like this below.

private boolean WifiConnected() {
            ConnectivityManager connMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
                    NetworkInfo networkInfo = connMgr.getNetworkInfo(ConnectivityManager.TYPE_WIFI); 
                    SupplicantState supState; 
                    WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
                    WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                    supState = wifiInfo.getSupplicantState();
                    return (networkInfo != null && networkInfo.isConnected() && supState.toString().contentEquals("COMPLETED"));
        }

So basically what I am checking before doing the background task is whether the device has active network connectivity and is connected or if the connection is wifi, if that connection is authentication complete so that data transfer is possible.

This doesn't seem to work and fails too making the service still force close.

What is the right way to do this check for network connectivity when wifi authentication is involved and then do the background processing?

Thanks.

A good example of this problem is when you are in any starbucks nationwide your android device will automatically connect to attwifi and the wifi status changes to connected because i check isConnected returns true but you will notice that the attwifi at starbucks will not let you transfer any data until you pseudo sign in by navigating to a browser page and accepting their terms of usage and agreement

Aakash
  • 3,101
  • 8
  • 47
  • 78

3 Answers3

0

You could move the connectivity check in your activity (or wherever else you have the context) and start the service from there.

Thus you won't have the force close constraint of the intentService and it should work fine.

Edit:

Ok got it! Here's what you can do to be sure that the user has access to Internet:

private boolean hasInternetAccess() {
    boolean hasInternetAccess = false;
    try {
            //I set google but you can try anything "reliable"...
            //isReachable(1) the timeout in seconds
        hasInternetAccess = InetAddress.getByName("www.google.com").isReachable(1);                         

    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return hasInternetAccess;
}

So your check becomes:

If(WifiConnected() && hasInternetAccess()){
  //Do background Work...
}

This is does some sort of ping to ensure the user has internet. Don't forget that this method needs to be executed in a separate thread or it'll throw a NetworkOnMainthreadException. Here you're safe since you are in an IntentService that has its own thread. But I precise for the ones that might see this thread. By the way I suggest you to change the title of the this thread since the actual problem is not really related to the service but the access to internet.

Here's the reference: Test Internet Connection Android

I hope this helps.

Community
  • 1
  • 1
ChrisCarneiro
  • 352
  • 1
  • 12
  • The use case is a bit different so the IntentService is executed periodically by AlarmManager. – Aakash Aug 29 '13 at 19:39
  • So just to clarify a little bit here cause it seems like I was a bit off...The problem is that your function WifiConnected() returns true even if you don't have access to the internet(you didn't accept the starbucks terms for example) ? Is that right ? – ChrisCarneiro Aug 29 '13 at 21:03
  • Correct. That causes the problem. The device thinks it is connected and can communicate to my servers for data when it actually cant and my app executes the background http request code to fetch data from the servers. – Aakash Aug 30 '13 at 02:28
0

Method conMgr.getActiveNetworkInfo() calls into ConnectivityService and the result of this call can be null. In the statement (conMgr.getActiveNetworkInfo() != null && conMgr.getActiveNetworkInfo().isAvailable() && conMgr.getActiveNetworkInfo().isConnected()) you call three times. I suspect there can be NPE here, as one of these calls can return null if network changes from 3g to WiFi at that time. What if you get NetworkInfo instance first, and them call isAvailable() and isConnected() on it (similar to how you did it in WifiConnected())?

sergej shafarenka
  • 20,071
  • 7
  • 67
  • 86
  • Ok I will try that but my point is when connected to a WEP or WPA2 Wifi or even open like my starbucks example isConnected returns true even when its actually not because the authentication is still not complete. – Aakash Aug 30 '13 at 02:31
0

or you can write a receiver for Connectivity change. It would be the best in your case.

<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
gaurav414u
  • 812
  • 13
  • 22