I have this service where I want to put the token as an interception in the okhttp instead of passing as a parameter with #Header("MY_API_KEY")
This is my code regarding the service
/**
* Provides the [PHService]
*/
fun provideService(): PHService {
val logger = HttpLoggingInterceptor()
logger.level = HttpLoggingInterceptor.Level.BASIC
val client = OkHttpClient.Builder()
.addInterceptor(logger)
.build()
return Retrofit.Builder()
.baseUrl(BuildConfig.API_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build()
.create(PHService::class.java)
}
How can I add an interceptor for header authorization in here?
add like this
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.header("Authorization", "MY_API_KEY"); // <-- this is the important line
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
httpClient.connectTimeout(30, TimeUnit.SECONDS);
httpClient.readTimeout(30, TimeUnit.SECONDS);
httpClient.addNetworkInterceptor(logging);
OkHttpClient client = httpClient.build();
in kotlin its like
val logging = HttpLoggingInterceptor()
logging.level = HttpLoggingInterceptor.Level.BODY
val httpClient = OkHttpClient.Builder()
httpClient.addInterceptor { chain ->
val original = chain.request()
// Request customization: add request headers
val requestBuilder = original.newBuilder()
.header("Authorization", "MY_API_KEY") // <-- this is the important line
val request = requestBuilder.build()
chain.proceed(request)
}
httpClient.connectTimeout(30, TimeUnit.SECONDS)
httpClient.readTimeout(30, TimeUnit.SECONDS)
httpClient.addNetworkInterceptor(logging)
val okHttpClient=httpClient.build()
In case you wish to add an api_key and an app_id in your requests as a query parameter using retrofit and OkHttp interceptors in kotlin. You can follow the following steps. This is useful so you dont have to pass the keys in every request in each query:
const val E_BASE_URL = "https://api.example.com"
const val API_ID = "YourApiID"
const val API_KEY = "YourApiKey"
//Here you add your url interceptor
//"app_id" and "app_key" might be different, depending on your API
val api_interceptor = Interceptor {
val originalRequest = it.request()
val newHttpUrl = originalRequest.url.newBuilder()
.addQueryParameter("app_id", API_ID)
.addQueryParameter("app_key", API_KEY)
.build()
val newRequest = originalRequest.newBuilder()
.url(newHttpUrl)
.build()
it.proceed(newRequest)
}
//Add the logger interceptor optional:
val logger = HttpLoggingInterceptor().apply { setLevel(HttpLoggingInterceptor.Level.BASIC) }
//Build your OkHttpClient - here you add the api_interceptor and logger
val clientHTTP = OkHttpClient().newBuilder()
.addNetworkInterceptor(logger) //optional
.addNetworkInterceptor(api_interceptor)
.build()
//Build your json converter - in this example MOSHI
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.build()
//FINALLY build your retrofit
val retrofitE = Retrofit.Builder()
.client(clientHTTP)
.baseUrl(E_BASE_URL)
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
//You can now declare your interfaces with your REST methods as usual, for example GET which will return your object
interface RecipesService {
#GET("search")
suspend fun getRecipes(
#Query("q") recipe: String,
): RecipeResponse
}
//Finally you create your object (Singleton in Java) which generates your service via lazy delegate
object RecipesAPI {
val retrofitService: RecipesService by lazy {
retrofitE.create(RecipesService::class.java)
}
}
For this example, you need to import following dependencies in the latest version:
com.squareup.retrofit2:retrofit
com.squareup.moshi:moshi-kotlin
com.squareup.retrofit2:converter-moshi
com.squareup.okhttp3:logging-interceptor
Related
I use OkHttp3 in Kotlin as a HTTP client and send Authorization Token Bearer header in request and return the result.
this is my code, but when run it the app closed :
RetrofitInstance.kt
class OAuthInterceptor(
private val tokenType: String,
private val acceessToken: String,
private val branchid : Int,
private val currency : Int,):Interceptor {
override fun intercept(chain: Interceptor.Chain): okhttp3.Response
{
var request = chain.request()
request = request.newBuilder()
.addHeader("Authorization", "$tokenType $acceessToken")
.addHeader("branchId", "$branchid")
.addHeader("currencyId", "$currency")
.build()
return chain.proceed(request)
}
}
class RetrofitInstance {
companion object {
private val client = OkHttpClient.Builder()
.addInterceptor(OAuthInterceptor(
"Bearer",
"YourToken",
123,
1)
)
.build()
val BASE_URL = "https://url"
fun getRetrofitInstance(): Retrofit {
return Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client).addConverterFactory(GsonConverterFactory.create(GsonBuilder().create()))
.build()
}
}
}
AlbumService.Kt
interface AlbumService {
#GET("users")
suspend fun getAlbums() : Response<Albums>
}
Album.kt
class Albums : ArrayList<dataapi>()
AlbumItem.kt
data class dataapi(
#SerializedName("address")
val address: String,
)
trying to use post/put call method in my Kotlin frontend to get response from Django backend. Method Get works but if I use ResponseBody nothing happens and log gives error with code 500.
Can someone help me?
This is my Api interface, where PUT and POST method doesnt work
public interface Api {
#GET("api/users")
fun getUsers(): Call<UserResults>
#PUT("/api/users/{Id}")
suspend fun updateUser(#Body requestBody: RequestBody, #Path("Id") userId: String): Response<ResponseBody>
#POST("/api/users")
suspend fun createUser(#Body requestBody: RequestBody): Response<ResponseBody>
}
This is function for example for PUT method
private fun updateSettings(preferredBranch: String) {
// Create Retrofit
val retrofit = Retrofit.Builder()
.baseUrl(BASE_URL)
.build()
// Create Service
val service = retrofit.create(Api::class.java)
// Create JSON using JSONObject
val jsonObject = JSONObject()
jsonObject.put("preferred_branch", preferredBranch)
//jsonObject.put("job", "iOS Developer")
// Convert JSONObject to String
val jsonObjectString = jsonObject.toString()
// Create RequestBody ( We're not using any converter, like GsonConverter, MoshiConverter e.t.c, that's why we use RequestBody )
val requestBody = jsonObjectString.toRequestBody("application/json".toMediaTypeOrNull())
CoroutineScope(Dispatchers.IO).launch {
// Do the PUT request and get response
val response = service.updateUser(requestBody, logId.toString())
withContext(Dispatchers.Main) {
if (response.isSuccessful) {
// Convert raw JSON to pretty JSON using GSON library
val gson = GsonBuilder().setPrettyPrinting().create()
val prettyJson = gson.toJson(
JsonParser.parseString(
response.body()
?.string() // About this thread blocking annotation : https://github.com/square/retrofit/issues/3255
)
)
Log.d("Pretty Printed JSON :", "test")
} else {
Log.e("RETROFIT_ERROR", response.code().toString())
}
}
}
}
OKHTTP Interceptor not working It gives me 401 Response(Unauthenticated/UnAuthorized)
Here is my Interceptor Class
InterceptorClass
class NetworkInterceptor(context: Context) : Interceptor {
private val applicationContext = context.applicationContext
private val sharedPreferenceData = SharedPreferenceData(applicationContext)
override fun intercept(chain: Interceptor.Chain): Response {
if (!isConnectionAvailable()) {
throw NoConnectionException("Error! Connecting to the network")
} else {
val requestBuilder = chain.request().newBuilder()
val token = sharedPreferenceData.getString("token", "")
requestBuilder.addHeader("Authorization", "Bearer $token")
Log.e("Token", "intercept: $token")
return chain.proceed(requestBuilder.build())
}
}
#Suppress("DEPRECATION")
fun isConnectionAvailable(): Boolean {
val cm =
applicationContext.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
cm.activeNetworkInfo.also {
return it != null && it.isConnected
}
}
}
Here is the network instance class
object NetworkInstance {
fun getApi(context: Context): DataApi {
val gsonBuilder = GsonBuilder()
gsonBuilder.setLenient()
val gson = gsonBuilder.create()
val logging = HttpLoggingInterceptor()
logging.setLevel(HttpLoggingInterceptor.Level.BODY)
val client = OkHttpClient
.Builder()
.addInterceptor(logging)
.addInterceptor(NetworkInterceptor(context))
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.addInterceptor(logging)
.build()
val retrofit = Retrofit
.Builder()
.client(client)
.baseUrl(BuildConfig.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build()
return retrofit.create(DataApi::class.java)
}
}
The issue was because of my Stupidity. I have added BASE_URL inside build.gradle which generates a Static Final variable inside BuildCondig.java which can't be altered. While Adding header BASE_URL can't be changed.
I have tried through almost every videos, articles and stackoverflow answer but I am not being able to cache the response in Retrofit.
I have retrofit setup is like this :
private val gson = GsonBuilder()
.setLenient()
.create()!!
private val CACHE_CONTROL = "Cache-Control"
private var cacheSize: Long = 10 * 1024 * 1024 // 10 MB
private var cache = Cache(File(applicationContext.cacheDir, "http-cache"), cacheSize)
private val offlineCacheInterceptor = Interceptor { chain ->
var request = chain.request()
Log.i("datatest", "Internet is availiable : ${isOnline(applicationContext)}")
if (!isOnline(applicationContext)) {
val cacheControl = CacheControl.Builder()
.maxStale(7, TimeUnit.DAYS)
.build()
request = request.newBuilder()
.cacheControl(cacheControl)
.build()
}
chain.proceed(request)
}
private val networkInterceptor = Interceptor { chain ->
val response = chain.proceed(chain.request())
val cacheControl = CacheControl.Builder()
.maxAge(2, TimeUnit.MINUTES)
.build()
response.newBuilder()
.header(CACHE_CONTROL, cacheControl.toString())
.build()
}
private val httpClient = OkHttpClient.Builder()
.addInterceptor(offlineCacheInterceptor)
.addNetworkInterceptor(networkInterceptor)
.cache(cache)
.build()
private val retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(httpClient)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
But when I try to call the retrofit APIs with my phone in Airplane mode
I get the following error :
Unable to resolve host "my_url": No address associated with hostname
What am I doing wrong in the cache setup?
I think there is a stupid mistake I have done but haven't seen by myself.
I know there isn't a static function in Kotlin, so I write two code in OkHttpService.kt and my.kt
I don't know which is better, could you tell me? Thanks!
OkHttpService.kt
class OkHttpService {
companion object {
fun httpGet(username: String, callback: Callback) {
val fetchRepoUrl = "https://api.github.com/users/$username/repos?page=1&per_page=20"
val client = OkHttpClient()
val request = Request.Builder()
.url(fetchRepoUrl)
.build()
client.newCall(request).enqueue(callback)
}
}
}
my.kt
fun OkHttpService_httpGet(username: String, callback: Callback) {
val fetchRepoUrl = "https://api.github.com/users/$username/repos?page=1&per_page=20"
val client = OkHttpClient()
val request = Request.Builder()
.url(fetchRepoUrl)
.build()
client.newCall(request).enqueue(callback)
For scoping use a regular object, not companion:
object OkHttpService{
fun httpGet(username: String, callback: Callback) {
val fetchRepoUrl = "https://api.github.com/users/$username/repos?page=1&per_page=20"
val client = OkHttpClient()
val request = Request.Builder()
.url(fetchRepoUrl)
.build()
client.newCall(request).enqueue(callback)
}
}