Reputation: 14628
Sometimes in API response, I get 401 Unauthorised status code. I tried to handle this here in my networkInterceptor, but still app crashes. Don't know what I am doing wrong, any help would be appreciated.
Here is my RetrofitFactory Class
object RetrofitFactory {
private val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(
OkHttpClient.Builder()
.addInterceptor(HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.addInterceptor(
object : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val request: Request = chain.request()
.newBuilder()
.build()
return chain.proceed(request)
}
}
)
.addNetworkInterceptor(
Interceptor { chain ->
val original = chain.request()
val requestBuilder = original.newBuilder()
val request = requestBuilder.build()
val response = chain.proceed(request)
Log.e("request", request.headers.toString())
Log.e("Response Body", response.body!!.toString())
when (response.code) {
HttpURLConnection.HTTP_OK -> return@Interceptor response
HttpURLConnection.HTTP_UNAUTHORIZED -> sessionExpired(
BaseApplication.getApplication()
)
HttpURLConnection.HTTP_FORBIDDEN -> sessionExpired(
BaseApplication.getApplication()
)
}
response
}
)
.build()
)
.build()
@JvmStatic
fun <S> createService(serviceClass: Class<S>): S {
return retrofit.create(serviceClass)
}
}
I want to move the user to Login Screen. So here is the function that should be called, but isn't calling.
fun sessionExpired(application: Application) {
val intent = Intent(application, LogInActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
application.startActivity(intent)
}
And here are my dependencies:
//retrofit
implementation 'com.squareup.retrofit2:retrofit:2.7.2'
implementation 'com.squareup.retrofit2:converter-gson:2.7.2'
//logging interceptor
implementation "com.squareup.okhttp3:logging-interceptor:4.4.0"
I also did look at here and many other similar questions, but didn't find help!
UPDATE ABOUT HOW I AM CALLING API:
in viewmodel with this
viewModelScope.launch(Dispatchers.IO) {
val apiResponse = apiEndPointsInterface.loginUser(loginRequestModel)
returnLoginResponse(apiResponse)
}
and the APIEndPointInterface is this
@POST(AppConstants.APIEndPoints.LOGIN_USER)
suspend fun loginUser(
@Body requestLoginModel: LoginRequestModel
): LoginResponseModel
Upvotes: 3
Views: 7856
Reputation:
To solve this kind of problems while making any api call or using retrofit. You must use cache strategy.Use Retrofit and Okhttp to solve your problem. It also helps you to prevent anywanted app crash during api calls, even your app not connected to internet.
Upvotes: 0
Reputation: 4528
You should call sessionExpired function in onFailure method the retrofit request.
override fun onFailure(call: Call<Model.Result>, t: Throwable) {
if(t is HttpException && t.statusCode==401)
sessionExpired(BaseApplication.getApplication())
}
If you are using Kotlin coroutines. You should wrap the await call in try catch block and call the function in catch block. See the below code:
val response: String
val getPlacesDeferred = PlaceAPI.retrofitService.getPlacesAsync()
response = getPlacesDeferred.await())
} catch (exception:Exception) {
if(exception is HttpException && t.statusCode==401)
sessionExpired(BaseApplication.getApplication())
}
Upvotes: 3