Код: Выделить всё
class ApiClient {
companion object {
private const val BASE_URL = "..." // API base URL
private var INSTANCE: Retrofit? = null
fun getInstance(context: Context): Retrofit {
if (INSTANCE == null) {
val builder = OkHttpClient.Builder()
val logging = HttpLoggingInterceptor()
logging.setLevel(HttpLoggingInterceptor.Level.BODY)
builder.addInterceptor(logging)
builder.addInterceptor(TokenInterceptor(context))
INSTANCE = Retrofit.Builder()
.baseUrl(BASE_URL)
.client(builder.build())
.addConverterFactory(GsonConverterFactory.create())
.build()
}
return INSTANCE!!
}
}
}
class TokenInterceptor(private val context: Context) : Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
val originalRequest = chain.request()
val accessToken = PreferenceUtil(context).getAccessToken()
Log.d("ApiClient", "Current token: $accessToken")
// Add access token to header if it exists
val requestWithToken = if (accessToken != null) {
originalRequest.newBuilder()
.header("Authorization", "Bearer $accessToken")
.build()
} else {
originalRequest
}
// Send request
var originalResponse = chain.proceed(requestWithToken)
if (originalResponse.code == 401) {
// Refresh token request
Log.e("ApiClient", "Token expired error, ${originalResponse.code}")
val refreshToken = PreferenceUtil(context).getRefreshToken()
Log.d("ApiClient", "Refresh token: $refreshToken")
if (refreshToken != null) {
Log.d("ApiClient", "Refresh token exists!")
// Asynchronous task to request a new access token
val newAccessToken = runBlocking {
reissueToken(refreshToken)
Log.d("ApiClient", "Why is this not working?")
}
newAccessToken?.let {
Log.d("ApiClient", "Replacing with new refresh token!")
val newRequest = originalRequest.newBuilder()
.header("Authorization", "Bearer $it")
.build()
originalResponse = chain.proceed(newRequest)
}
}
}
return originalResponse
}
private suspend fun reissueToken(refreshToken: String): String? {
return withContext(Dispatchers.IO) {
val apiService = ApiClient.getInstance(context).create(LogInService::class.java)
val response = apiService.reissueToken(refreshToken)
Log.d("ApiClient", "Receiving new response: ${response}")
if (response.isSuccessful) {
Log.d("ApiClient", "Response successful")
response.body()?.let { tokenResponse ->
Log.d("ApiClient", "Token successfully renewed")
PreferenceUtil(context).setAccessToken(tokenResponse.accessToken)
PreferenceUtil(context).setRefreshToken(tokenResponse.refreshToken)
return@withContext tokenResponse.accessToken
}
} else {
Log.d("ApiClient", "Response failed...")
null
}
}
}
}
- ApiClient: инициализирует модернизацию с помощью OkHttpClient и добавляет TokenInterceptor.< /li>
TokenInterceptor: перехватывает запросы и проверяет токен доступа. Если он получает ответ 401, он пытается обновить токен.
"Текущий токен: $accessToken"
"Ошибка срока действия токена, 401"
"Обновить токен: $refreshToken"
«Обновить токен существует!»
Подробнее здесь: https://stackoverflow.com/questions/791 ... ith-okhttp
Мобильная версия