Network Requests with Retrofit in Android

Jun 5 2024 · Kotlin 1.9.22, Android 14, Android Studio Hedgehog | 2023.1.1

Lesson 06: Interceptors and Authentication

Demo

Episode complete

Play next episode

Next

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Heads up... You’re accessing parts of this content for free, with some sections shown as obfuscated text.

Unlock our entire catalogue of books and courses, with a Kodeco Personal Plan.

Unlock now

Start by adding the following dependency to the app module’s build.gradle file:

implementation "com.squareup.okhttp3:logging-interceptor:4.12.0"
private fun buildLoggingInterceptor() = HttpLoggingInterceptor()
  .setLevel(if (BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE)
private fun buildClient(): OkHttpClient = OkHttpClient.Builder()
  .addNetworkInterceptor(buildLoggingInterceptor())
  .build()
private fun buildAuthInterceptor() = Interceptor { chain ->
  val newRequest = chain.request()
    .newBuilder()
    .addHeader("Authorization", "Bearer ${App.getUserToken()}")
    .build()
  chain.proceed(newRequest)
}
private fun buildClient(): OkHttpClient = OkHttpClient.Builder()
  .addNetworkInterceptor(buildAuthInterceptor())
  .addNetworkInterceptor(buildLoggingInterceptor())
  .build()
suspend fun getProfile(): Result<User> = runCatching { apiService.getProfile() }

suspend fun postReview(movieReview: MovieReview): Result<MovieReview> =
  runCatching { apiService.postReview(movieReview) }
@GET("movies")
suspend fun getMovies(): List<MovieReview>
NewEntryDialog(
  onDismissRequest = { openDialog = false },
  onConfirmation = { movieReview ->
    screenScope.launch {
      movieDiaryApi.postReview(movieReview)
        .onSuccess { newReview ->
          val newList = movieReviewList.toMutableList()
          newList += newReview
          movieReviewList = newList
        }
        .onFailure { scaffoldState.snackbarHostState.showSnackbar(it.message ?: "") }
    }
    openDialog = false
  },
)
LaunchedEffect(Unit) {
  movieDiaryApi.getProfile()
    .onSuccess { user = it }
    .onFailure { scaffoldState.snackbarHostState.showSnackbar(it.message ?: "") }
}
@POST("user/refreshToken")
suspend fun refreshToken(@Body refreshToken: Long): LoginResponse
suspend fun refreshToken(refreshToken: Long): Result<LoginResponse> = runCatching {
  apiService.refreshToken(refreshToken)
}
class ApiAuthenticator : Authenticator {
  override fun authenticate(route: Route?, response: Response): Request? {
    runBlocking {
      App.movieApi.refreshToken(App.getRefreshToken())
    }.onSuccess {
      App.saveUserToken(it.token)
      return response.request.newBuilder()
        .addHeader("Authorization", "Bearer ${it.token}")
        .build()
    }
    return null
  }
}
private fun buildClient(): OkHttpClient = OkHttpClient.Builder()
  .addNetworkInterceptor(buildAuthInterceptor())
  .addNetworkInterceptor(buildLoggingInterceptor())
  .authenticator(ApiAuthenticator())
  .build()
See forum comments
Cinema mode Download course materials from Github
Previous: Instruction Next: Conclusion