I am having a wierd problem.
@Singleton
class AppInterceptor @Inject constructor() : Interceptor {
private var accessToken: String? = null
fun setAccessToken(accessToken: String?) {
this.accessToken = accessToken
Log.d("Tag", "Access Setting: ${this.accessToken}")
}
override fun intercept(chain: Interceptor.Chain): Response {
val request: Request = chain.request()
val requestBuilder: Request.Builder = request.newBuilder()
accessToken?.let { requestBuilder.addHeader("authorization", "Bearer $it") }
return chain.proceed(requestBuilder.build())
}
}
In the code above, after calling the setAccessToken(accessToken: String?)
the first Log prints the right token, but the intercept
function always gets accessToken = null
. I have been struggling with this problem for hours. Does anyone know why I'm getting this issue?
To update the accessToken, I have injected the interceptor into a viewModel, then I called the setAccessToken function.
@HiltViewModel
class ApiViewModel @Inject constructor(
private val apiHelper: APIHelper,
private val oktaManager: OktaManager,
private val interceptor: AppInterceptor
) : AndroidViewModel() {
fun getResult() {
viewModelScope.launch(Dispatchers.IO) {
interceptor.setAccessToken(oktaManager.gettingOktaToken())
try {
apiHelper.getResults()
} catch (e: Exception) {
Log.e("error", e.toString())
}
}
}
}
Here is the Retrofit builder
@Module
@InstallIn(SingletonComponent::class)
object RetrofitBuilder {
private const val BASE_URL = "https://myUrl"
private val interceptor = run {
val httpLoggingInterceptor = HttpLoggingInterceptor()
httpLoggingInterceptor.apply {
httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
}
}
@Singleton
@Provides
fun provideOkHTTPClient(): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(interceptor)
.apply { addInterceptor(AppInterceptor()) }
.addInterceptor(interceptor)
.build()
}
@Singleton
@Provides
fun provideObjectMapper(): ObjectMapper {
return jacksonObjectMapper().registerModule(JavaTimeModule())
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false)
}
@Singleton
@Provides
fun provideRetrofitInstance(
client: OkHttpClient,
objectMapper: ObjectMapper
): Retrofit {
return Retrofit.Builder()
.client(client)
.baseUrl(BASE_URL)
.addConverterFactory(JacksonConverterFactory.create(objectMapper))
.build()
}
@Singleton
@Provides
fun provideApiService(retrofit: Retrofit): IApiService {
return retrofit.create(IApiService::class.java)
}
}
CodePudding user response:
One thing you can try is to set the data in Shared preference in AppViewModel and get that in intercept funtion. One thing needs to be validated is interceptor instance used by retrofit and viewmodel are same .As its singleton injection , the access token should updating the existing object. Not sure why its not working.
Update: You need add AppInterceptor injection in provideOkHttpClient() and use that object to addInterceptor()
@Singleton
@Provides
fun provideOkHTTPClient(appInterceptor:AppInterceptor): OkHttpClient {
return OkHttpClient.Builder()
.addInterceptor(interceptor)
.apply { addInterceptor(appInterceptor) }
.addInterceptor(interceptor)
.build()
}