1

I have this when(kotlin)/switch case(java) which gets java.net exceptions for my requests. The problem is that it throws UnknownHostException for two cases:

  1. When I have no connection.

  2. When I insert a broken url (that would be the equivalent to server completely unavailable).

How can I differentiate this two cases if they throw the same exception? Should I check the user's connection before every request?

when/try catch

            is SocketTimeoutException -> {
                 //Server takes too long to respond
            }
            is UnknownHostException -> {
                 //No connection and broken url / no server at all
            }
            is HttpException -> {
                 //server error response
            }
            else -> {
                 //Any other case
            }
  • I would think best practice would be to check if you have connection before performing the request at all, which would eliminate that possibility entirely. – Myk Jan 16 '20 at 01:11

2 Answers2

3

you need a create a Exception like a Interceptor in you OkHttpClient:
in OkHttpClient: .addInterceptor(ConnectivityInterceptor(context))


class ConnectivityInterceptor(private val mContext: Context) : Interceptor {
    @Throws(IOException::class)
    override fun intercept(chain: Chain): Response {
        if (!NetworkUtil.isOnline(mContext)) {
            throw NoInternet()
        }
        val builder = chain.request().newBuilder()
        return chain.proceed(builder.build())
    }

}


class NoInternet : IOException() {

    override val message: String?
        get() {
            return "No connectivity exception"
        }

}

class NetworkUtil {
    companion object {
        fun isOnline(context: Context): Boolean {
            var result = false
            val connectivityManager =
                context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                val networkCapabilities = connectivityManager.activeNetwork ?: return false
                val actNw =
                    connectivityManager.getNetworkCapabilities(networkCapabilities) ?: return false
                result = when {
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> true
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> true
                    actNw.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> true
                    else -> false
                }
            } else {
                connectivityManager.run {
                    connectivityManager.activeNetworkInfo?.run {
                        result = when (type) {
                            ConnectivityManager.TYPE_WIFI -> true
                            ConnectivityManager.TYPE_MOBILE -> true
                            ConnectivityManager.TYPE_ETHERNET -> true
                            else -> false
                        }
                    }
                }
            }
            return result
        }
    }
}

and you use in when

       is NoInternet -> {
}
0

After some Googleing and browsing thru some articles I think that the best way to make it right is to check if the client is already connected to the internet.

Method 1

public static boolean isNetworkAvailable (Context context) {  
    if (connectedToTheNetwork(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) 
                (new URL("http://clients3.google.com/generate_204")
                .openConnection());
            urlc.setRequestProperty("User-Agent", "Android");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 204 &&
                        urlc.getContentLength() == 0);
        } catch (IOException e) {
            Log.e(TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(TAG, "No network available!");
    }
    return false;
}

Source

Method 2

 fun verifyAvailableNetwork(activity:AppCompatActivity):Boolean{
      val connectivityManager=activity.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
      val networkInfo=connectivityManager.activeNetworkInfo
      return  networkInfo!=null && networkInfo.isConnected
}

Source

Method 3

val Context.isConnected: Boolean
    get() {
        return (getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager)
           .activeNetworkInfo?.isConnected == true
    }

Source

I haven't tested them out, but all of them make sense and frankly speaking I'd start from the 3rd one to 1st. The simpler, the better.

Hope it will work out!

Community
  • 1
  • 1
  • I knew that I could call this kind of functions to check for connection before making the request. I would like to get an exception for this kind of error. – Igor Grecco Lacourt Jan 22 '20 at 13:41