I am new on android.Can any one tell me how to add the header for api_key using retrofit.I am not able to understand how i can do this.
I find this code from net.where i have to put this code in android folder structure.I am confused with this.where i have to add api_key.
// Define the interceptor, add authentication headers
Interceptor interceptor = new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request newRequest = chain.request().newBuilder().addHeader("User-Agent", "Retrofit-Sample-App").build();
return chain.proceed(newRequest);
}
};
// Add the interceptor to OkHttpClient
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.interceptors().add(interceptor);
OkHttpClient client = builder.build();
// Set the custom client when building adapter
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
You can store your api_key in your strings.xml file like this:
<string name="your_api_key_id" translatable="false">YOUR_API_KEY</string>
Then, in your OkHttpClient definition class, write a method to build your OkHttpClient like that:
private final static String API_KEY_IDENTIFIER = "key_identifier";
private OkHttpClient getHttpClient(){
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
HttpUrl originalUrl = original.url();
HttpUrl url = originalUrl.newBuilder()
.addQueryParameter(API_KEY_IDENTIFIER, mContext.getString(R.string.your_api_key_id))
.build();
Request.Builder requestBuilder = original.newBuilder().url(url);
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
return httpClient.build();
}
You should implement your client builder class with Singleton pattern, in order to have the client build centralized in one place inside your code
Related
I'm uploading a file using Retrofit to AWS S3, however the content-type is being overridden everytime I upload. I have the the CONTENT-TYPE audio/mp3 however the file on S3 is being overridden as content-type multiformpartbody/form-data. What am I doing incorrectly?
File file = new File(String.valueOf(Uri.parse(selectedImagesList.get(current_image_uploading))));
ProgressRequestBody requestFile = new ProgressRequestBody(file, "audio/mp3");
MultipartBody.Part body =
MultipartBody.Part.createFormData("audio", file.getName(), requestFile);
RetrofitInterfaces.IUploadMP3 service = RetrofitClientInstance.getRetrofitInstance()
.create(RetrofitInterfaces.IUploadMP3.class);
Call<Void> call = service.listRepos(uploadUrls.get(current_image_uploading), body);
Most likely you need to override the header when you send the request. You can either do it for each request:
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("Content-Type"," audio/mpeg") //Set the content type here
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
}
OkHttpClient client = httpClient.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
Or, if you don't want to override every request, you can do a static override for your call like so:
public interface YourService {
#Headers("Content-Type: audio/mpeg")
#GET("/your/path")
Call<List<Task>> myFunction();
}
Both examples can be found here:
I have query parameters that is used for all requests. It is added to the base url as follow
private val baseUrl = HttpUrl.Builder()
.scheme("http")
.host("ws.audioscrobbler.com")
.addPathSegment("2.0")
.addPathSegment("")
.addQueryParameter("format", "json")
.addQueryParameter("api_key", "val")
.build()
retrofit = Retrofit.Builder()
.baseUrl(baseUrl)
.client(okHttpClient)
.build()
The api service call is
#GET("./")
fun searchTracks(#Query("otherParam") query: String): Call<Any>
The url is built correctly till the actual call is made. It removes the query params added in the base url and keeps only the one added in service call.
Shown in debugging till the delegate.enqueue() is called in ExecutorCallAdapterFactory:"http://ws.audioscrobbler.com/2.0/?format=json&api_key=val&otherParam=val"
shown in logs (via interceptor): "http://ws.audioscrobbler.com/2.0/?otherParam=val"
Any idea why this happens and how to keep the parameters?
You should add query parameters to url in request interceptor.
OkHttpClient.Builder httpClient =
new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request original = chain.request();
HttpUrl originalHttpUrl = original.url();
HttpUrl url = originalHttpUrl.newBuilder()
.addQueryParameter("format", "json")
.addQueryParameter("api_key", "val")
.build();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.url(url);
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
I am creating an application with retrofit2 for network calls. I need call multiple API in Single Activity. Now I am facing the 403-forbidden error. If I call only one API it is working fine. But if I use multiple API calls one by one then I am facing this error.
My CreateService method is below:
public static <S> S createService(Class<S> serviceClass, final String authToken) {
if (authToken != null) {
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-Token", authToken)
.method(original.method(), original.body());
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
}
// OkHttpClient client = httpClient.readTimeout(60, TimeUnit.SECONDS).connectTimeout(60, TimeUnit.SECONDS).build();
Dispatcher dispatcher = new Dispatcher(Executors.newFixedThreadPool(200));
dispatcher.setMaxRequests(200);
dispatcher.setMaxRequestsPerHost(1);
OkHttpClient okHttpClient = httpClient.dispatcher(dispatcher).connectionPool(new ConnectionPool(100, 30, TimeUnit.SECONDS)).build();
Retrofit retrofit = builder.client(okHttpClient).build();
return retrofit.create(serviceClass);
}
What is wrong in my code.. How can I handle this?
Are you sure that string is not empty string?
Could you please add log interceptor and set the log level and provide a log?
compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
And sth like this :
OkHttpClient.Builder okBuilder = new OkHttpClient.Builder();
okBuilder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BASIC).setLevel
(HttpLoggingInterceptor.Level.BODY).setLevel(HttpLoggingInterceptor.Level.HEADERS))
im trying to consume an api that has that authorization header, i can get a 200 response in Postman with all data but cant get it to work in retrofit
May be you need add the Token using OkHttp Interceptor.
OkHttpClient client = new OkHttpClient.Builder()
.addNetworkInterceptor(mTokenInterceptor)
.build();
then add it to Retrofit:
Retrofit retrofit = new Retrofit.Builder()
.client(client)
.baseUrl(base_url)
.build();
the mTokenInterceptor:
Interceptor mTokenInterceptor = new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
if (mToken != null) {
Request.Builder requestBuilder = request.newBuilder()
.addHeader("Authorization", mToken);
Request newRequest = requestBuilder.build();
return chain.proceed(newRequest);
}
return chain.proceed(request);
}
};
when you get the Token, just assign the mToken,
You can try something like below, just a crude example
#GET("your server url goes here")
Call<Your_Model_Class> getServerData(#Header("Authorization") String token);
Pass your token to getServerData method.
I am using okhttp 2.0 in my Android app and didn't find a way to set some common User Agent for all outgoing requests.
I thought I could do something like
OkHttpClient client = new OkHttpClient();
client.setDefaultUserAgent(...)
...but there's no such method or similar.
Of course I could provide some extension utility method which would wrap a RequestBuilder to attach .header("UserAgent") and then I would use it for building all my requests, but I thought maybe I missed some existing and simpler way?
You can use an interceptor to add the User-Agent header to all your requests.
For more information about okHttp interceptors see http://square.github.io/okhttp/interceptors/
Example implementation of this interceptor:
/* This interceptor adds a custom User-Agent. */
public class UserAgentInterceptor implements Interceptor {
private final String userAgent;
public UserAgentInterceptor(String userAgent) {
this.userAgent = userAgent;
}
#Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request requestWithUserAgent = originalRequest.newBuilder()
.header("User-Agent", userAgent)
.build();
return chain.proceed(requestWithUserAgent);
}
}
Test for the UserAgentInterceptor:
public void testUserAgentIsSetInRequestHeader() throws Exception {
MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setBody("OK"));
server.play();
String url = server.getUrl("/").toString();
OkHttpClient client = new OkHttpClient();
client.networkInterceptors().add(new UserAgentInterceptor("foo/bar"));
Request testRequest = new Request.Builder().url(url).build()
String result = client.newCall(testRequest).execute().body().string();
assertEquals("OK", result);
RecordedRequest request = server.takeRequest();
assertEquals("foo/bar", request.getHeader("User-Agent"));
}
In case anyone is looking for this working with OkHttp 3 and in Kotlin:
val client = OkHttpClient.Builder()
.addNetworkInterceptor { chain ->
chain.proceed(
chain.request()
.newBuilder()
.header("User-Agent", "COOL APP 9000")
.build()
)
}
.build()
OkHttp v2.1 which is set to be released in the next few weeks will automatically set a User-Agent header if one is not already set.
As of now there isn't a good way to add this header to every request in a centralized way. The only workaround is to include the header manually for every Request that is created.
Based on #josketres answer, here is a similar Interceptor for OkHttp version 3
public class UserAgentInterceptor implements Interceptor {
private final String mUserAgent;
public UserAgentInterceptor(String userAgent) {
mUserAgent = userAgent;
}
#Override
public Response intercept(#NonNull Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
.header("User-Agent", mUserAgent)
.build();
return chain.proceed(request);
}
}
Plus the updated test:
#Test
public void testUserAgentIsSetInRequestHeader() throws IOException, InterruptedException {
final String expectedUserAgent = "foo/bar";
MockWebServer server = new MockWebServer();
server.enqueue(new MockResponse().setBody("OK"));
server.start();
OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder();
okHttpBuilder.addInterceptor(new UserAgentInterceptor(expectedUserAgent));
Request request = new Request.Builder().url(server.url("/").url()).build();
ResponseBody result = okHttpBuilder.build().newCall(request).execute().body();
assertNotNull(result);
assertEquals("OK", result.string());
assertEquals(expectedUserAgent, server.takeRequest().getHeader("User-Agent"));
}
You have to use builder in newer versions. (Sep 2021)
client = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#NotNull
#Override
public Response intercept(#NotNull Chain chain) throws IOException {
Request originalRequest = chain.request();
Request requestWithUserAgent = originalRequest.newBuilder()
.header("User-Agent", "My Agent is so cool")
.build();
return chain.proceed(requestWithUserAgent);
}
})
.build();
Using an intercepter is no longer required in the newer versions of OkHttp. Adding a user agent is as simple as:
Request request = new Request.Builder()
.url("http://www.publicobject.com/helloworld.txt")
.header("User-Agent", "OkHttp Example")
.build();
Source: OkHttp wiki.