0

I'm trying to make my app check if it is able to connect to the internet.

My research tells me that network-level connectivity doesn't necessarily mean you can access remote sites / services. For example:

Detect if Android device has Internet connection

I have tried the solutions in that Q&A, and they "sort of" work. My problem is that urlc.setConnectTimeout(50000) (i.e. a 50 second timeout) doesn't seem to have any effect. Instead, my application is reporting an error almost immediately.

I want my application to keep trying to connect for some time before reporting a failure.

Stephen C
  • 632,615
  • 86
  • 730
  • 1,096
Omar Labib
  • 55
  • 8
  • You can make your request perform certain number of retrials if it fails with specific exception, is that what you are looking for? – elmorabea Dec 30 '17 at 00:36
  • @elmorabea..it may work, but should not (setConnectTimeout(50000)) keep trying for the specified time? – Omar Labib Dec 30 '17 at 00:55
  • No, connection time out, will allow this time (50 seconds) for a connection to be established, if a connection couldn't be established by then, it will throw a time out exception, but the timeout API doesn't promise any retrying, you need to do that – elmorabea Dec 30 '17 at 00:58
  • @elmorabea let me make sure I get this clearly.. the device tries to connect within the (50 seconds) but not necessarily for the whole (seconds), unless a connection is establish, it throws the error.. right? but if a connection is already established, after (50 seconds) is it terminated? – Omar Labib Dec 30 '17 at 01:08
  • @OmarLabib - Is my edit to your question correct? If not, feel free to roll it back. – Stephen C Dec 30 '17 at 01:11
  • Yes, basically you are telling your request object you have 50 seconds to connect, if you cannot connect in 50 second or less, please stop waiting and throw an exception. – elmorabea Dec 30 '17 at 01:11
  • @StephenC, even much better :D – Omar Labib Dec 30 '17 at 01:14
  • https://stackoverflow.com/a/42229749/5610842 Check this answer let me know if you found it useful – RaghavPai Jan 04 '18 at 09:15

2 Answers2

0

The Android system already does that for you. Instead of constantly polling the phone for the network state, register BroadcastReceivers for WiFi and network state changes and process the Intents sent by the system when the WiFi or network state changes.

You should make a BroadcastReceiver that will be triggered when the connectivity status has changed.

NetworkChangeReceiver.java

 public class NetworkChangeReceiver extends BroadcastReceiver
  {
   @Override
    public void onReceive(final Context context, final Intent intent)
    {
    String status = NetworkUtil.getConnectivityStatusString(context);
    Toast.makeText(context, status, Toast.LENGTH_LONG).show();
     }
     }

NetworkUtil.java

    public class NetworkUtil
   {
 public static int TYPE_WIFI = 1;
  public static int TYPE_MOBILE = 2;
 public static int TYPE_NOT_CONNECTED = 0;
  public static int getConnectivityStatus(Context context) 
  {
   ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
 NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
 if (null != activeNetwork) 
 {
 if(activeNetwork.getType() == ConnectivityManager.TYPE_WIFI)
   return TYPE_WIFI;
   if(activeNetwork.getType() == ConnectivityManager.TYPE_MOBILE)
  return TYPE_MOBILE;
  }
   return TYPE_NOT_CONNECTED;
}
 public static String getConnectivityStatusString(Context context)      
 { 
  int conn = NetworkUtil.getConnectivityStatus(context);
    String status = null;
   if (conn == NetworkUtil.TYPE_WIFI)
  {
 status = "Wifi enabled";
 }
 else if (conn == NetworkUtil.TYPE_MOBILE) 
{
status = "Mobile data enabled";
}
   else if (conn == NetworkUtil.TYPE_NOT_CONNECTED)
    {
 status = "Not connected to Internet";
  }
    return status;
    }
    }

Add Required Permission and Receiver in Androidmanifest.xml

Gopal
  • 570
  • 8
  • 26
0

The most likely explanation for your problem is that there are many possible reasons why your app may not be able to connect. These include:

  • Your app may not have permission to connect
  • The user's device could be out of mobile data or wifi range
  • The internet may have been disabled by the user
  • You may be trying to connect to a host whose IP or DNS entry is incorrect
  • The host or its home network may be temporarily offline
  • The service may not be running on the host
  • The service may be broken
  • There could be a some other networking issue affecting connectivity.

The "problem" is that only some of these manifest as a connection timeout. Others (e.g. incorrect DNS entries, local networking problems, service not running, etc) will typically result in a different symptom; e.g. a DNS lookup failure, a "Connection Refused", a "No route to network", etc. These typically occur immediately, and the network stack does not attempt to retry.

As mentioned in the comment, the solution is to implement a retry loop.

  • You need to discriminate the different kinds of failure ... based on the exception thrown.
  • For "timeout" exceptions, don't retry.
  • For exceptions that indicate a failure that won't recover (e.g. network permissions, no DNS entry, etc), retry is pointless.
  • For others, implement your own timer and retry logic.

Yes ... it is a bit complicated to implement this. And there are some traps. For example, it is unwise to have the retry logic attempt to retry immediately or for too many repetitions, as these can behave as "denial of service" attacks on the remote service.

Stephen C
  • 632,615
  • 86
  • 730
  • 1,096