question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

App crashes on throwing the exception from the Interceptor

See original GitHub issue

There are the implementations i have been using

implementation 'com.squareup.retrofit2:retrofit:2.6.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.6.0'
implementation 'com.squareup.okhttp3:okhttp:4.2.1'
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'

This is the network interceptor class

class NetworkConnectionInterceptor(
    context: Context
) : Interceptor {


    private val applicationContext = context.applicationContext

    override fun intercept(chain: Interceptor.Chain): Response {
        return if (!isConnectionOn()) {
            throw NoConnectivityException()
        } else if(!isInternetAvailable()) {
            throw NoInternetException()
        } else {
            chain.proceed(chain.request())
        }
    }

    private fun isInternetAvailable(): Boolean {
        return try {
            val timeoutMs = 1500
            val sock = Socket()
            val sockaddr = InetSocketAddress("8.8.8.8", 53)

            sock.connect(sockaddr, timeoutMs)
            sock.close()

            true
        } catch (e: IOException) {
            false
        }
    }

    private fun isConnectionOn(): Boolean {
        val connectivityManager =
            applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as
                    ConnectivityManager

        return if (android.os.Build.VERSION.SDK_INT >=
            android.os.Build.VERSION_CODES.M) {
            postAndroidMInternetCheck(connectivityManager)
        } else {
            preAndroidMInternetCheck(connectivityManager)
        }
    }

    @RequiresApi(Build.VERSION_CODES.M)
    private fun postAndroidMInternetCheck(
        connectivityManager: ConnectivityManager): Boolean {
        val network = connectivityManager.activeNetwork
        val connection =
            connectivityManager.getNetworkCapabilities(network)

        return connection != null && (
                connection.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
                        connection.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR))
    }

    private fun preAndroidMInternetCheck(
        connectivityManager: ConnectivityManager): Boolean {
        val activeNetwork = connectivityManager.activeNetworkInfo
        if (activeNetwork != null) {
            @Suppress("DEPRECATION")
            return (activeNetwork.type == ConnectivityManager.TYPE_WIFI ||
                    activeNetwork.type == ConnectivityManager.TYPE_MOBILE)
        }
        return false
    }

}

My Retrofit client

operator fun invoke(
            networkConnectionInterceptor: NetworkConnectionInterceptor
        ): ApiUtil {

            val builder = OkHttpClient.Builder()
            builder.connectTimeout(5, TimeUnit.SECONDS)
            builder.writeTimeout(10, TimeUnit.SECONDS)

            val interceptor = HttpLoggingInterceptor()
            interceptor.level = HttpLoggingInterceptor.Level.BODY

            val client = OkHttpClient.Builder()
                .addInterceptor(interceptor)
                .addInterceptor(networkConnectionInterceptor)
                .build()


            builder.cache(null)

            val gson = GsonBuilder()
                .setLenient()
                .create()

            val retrofit = Retrofit.Builder()
                .baseUrl(BASE_URL)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .client(client)
                .build()

            return retrofit.create(ApiUtil::class.java)
            
        }

this is how i am calling the api’s

fun onGetNationalities() {
        try {
            responseCallback?.onStarted()
            Coroutines.main {
                val nationalitiesResponse = repository.getNationalities()
                nationalitiesResponse?.let {
                    if (it.success) {
                        responseCallback?.onSuccess(it)
                    } else {
                        responseCallback?.onFailure(it.errorMessage)
                    }
                }
            }
        } catch (e: Exception) {
            responseCallback?.onAlert(
                e.cause?.localizedMessage
                    ?: MessageUtils.SOMETHING_WENT_WRONG
            )
        } catch (e: NoInternetException) {
            responseCallback?.onAlert(e.message!!)
        }catch (e: NoConnectivityException) {
            responseCallback?.onAlert(e.message!!)
        }
    }

NoInternetException and NoConnectivityException are two exception classes

class NoConnectivityException : IOException() {
    override val message: String
        get() =
            "No network available, please check your WiFi or Data connection"
}
class NoInternetException() : IOException() {
    override val message: String
        get() =
            "No internet available, please check your connected WIFi or Data"
}

This is not happening everytime for example if i am calling an api on button click and internet is not active, exception thrown from the intercepor will be caught in the function from where i am calling the api but if i call an api on the start on e.g signup form so i can get the nationalities for signup as in my example the interceptor will crash while throwing the exception plus it also crash sometime on the chain.proceed with the Sockettimeoutexception etc. The crash is reproducible.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:22 (5 by maintainers)

github_iconTop GitHub Comments

1reaction
swankjessecommented, Oct 30, 2019

If you throw an unchecked exception in an interceptor, OkHttp will report that to the uncaught exception handler. You can throw IOException instead if you want to catch it.

1reaction
AhmadIzazcommented, Oct 28, 2019

I have tried with these too but still crashing

implementation 'com.squareup.retrofit2:retrofit:2.6.2'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-gson:2.6.2'
implementation 'com.squareup.okhttp3:okhttp:4.2.2'
implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
Read more comments on GitHub >

github_iconTop Results From Across the Web

Retrofit crashes when I throw an exception in an interceptor
I have an interceptor that handles some authentication things. If the authentication fails it throws and Exception.
Read more >
Throwing IOException in Interceptor is causing the crash with ...
I was using onErrorReturn method as I was using flatmap to call multiple network calls in chains. The side effect of this was...
Read more >
Retrofit crashes when I throw an exception in an interceptor
I have an interceptor that handles some authentication things. If the authentication fails it throws and Exception. According to what I could find...
Read more >
Interceptor - OkHttp
The interceptor's exception is delivered to the current thread's uncaught exception handler. By default this crashes the application on Android and prints a ......
Read more >
Exceptions in coroutines. Cancellation and Exceptions in…
In this case, if async throws an exception, it will get thrown as soon as it happens because the coroutine that is the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found