Kishan Solanki
Kishan Solanki

Reputation: 14628

Android App Crash : retrofit2.HttpException: HTTP 401

enter image description hereSometimes 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

Answers (2)

user13651827
user13651827

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

Ravi Kumar
Ravi Kumar

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

Related Questions