okhttp: App crashes on throwing the exception from the Interceptor
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.
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Comments: 23 (5 by maintainers)
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.
Hi @swankjesse I am working on android native kotlin project. Please find below details from build.gradle file for latest okhttp and retrofit dependencies which I am using for project. okhttp
implementation "com.squareup.okhttp3:okhttp:4.9.0"
implementation "com.squareup.okhttp3:logging-interceptor:4.9.0"
Retrofitimplementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
I have already set relevant timeouts for okhttp client.
I am using okhttp3.Interceptor. Please find implementation below.
Observations / Issues
return chain.proceed(requestBuilder.build())
I have figured out below okhttp internal crashes logs from my android studio that can help you to find root cause and fixes.
I also tried to wrap above Interceptor snippets using try-catch but still okhttp3 itself crashing so app is crashing. We don’t have any control to solve it. Please find below Interceptor snippets with wrapped try-catch implementation.
You can also try to make small android project with relevant setup and snippets and see. Please provide necessary fixes for this blocker issue as many people are facing in the world. Please let me know in case you need more details. I would more than happy to provide you.
I have tried with these too but still crashing