My API having some verification mechanism for every HTTP request. One of the end-point have the functionality to load a image using HTTP post method. The post request body will contain a JSON object which is verified from the server side.
For that i need to include a JSON like this on the http post request body.
{
"session_id": "someId",
"image_id": "some_id"
}
how can I do this with Picasso ?
I got the solution from the hint given by Mr.Jackson Chengalai.
Create a Okhttp request interceptor
private static class PicassoInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
Map<String, String> map = new HashMap<String, String>();
map.put("session_id", session_id);
map.put("image", image);
String requestJsonBody = new Gson().toJson(map);
RequestBody body = RequestBody.create(JSON, requestStringBody);
final Request original = chain.request();
final Request.Builder requestBuilder = original.newBuilder()
.url(url)
.post(body);
return chain.proceed(requestBuilder.build());
}
}
Create a Okhttp client add this interceptor
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.interceptors().add(new PicassoInterceptor());
Create a Dowloader using this okhttp client
OkHttpDownloader = downloader = new OkHttpDownloader(okHttpClient)
Build Picasso using this downloader
Picasso picasso = new Picasso.Builder(context).downloader(downloader ).build();
Related
In my app image contents are changing frequently (like once in a week) and imageurl remains the same. I am using picasso for image loading. My query is to can I set age to cache-entry and use the headers like 'if-modified-since' and 'ETag'?
This is how I resolved it.
Interceptor interceptor = new Interceptor() {
public static final String TAG = "RequestInterceptor";
#Override
public Response intercept(Chain chain) throws IOException {
final Request original = chain.request(); //Original request initiated
final Response response; //Response for given url
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder().header("if-modified-since", last-modified-date-for-image).method(original.method(), original.body());
Request request = requestBuilder.build();
response = chain.proceed(request);
Log.d(TAG, "Intercepting status code : " + response.code());
Log.d(TAG, "Intercepting requests : Url :" + request.url().toString());
Log.d(TAG, "Intercepting requests : if-modified-since : " + response.header("if-modified-since".toLowerCase()));
/* if response code is 200 means we have updated image otherwise return older one.*/
if (response.code() == 200) {
return response;
} else {
return chain.proceed(original);
}
}
};
//Create OkHttpClient for picasso downloader and add request interceptor.
OkHttpClient okHttpClient = new OkHttpClient.Builder().addInterceptor(interceptor).build();
//Instantiate okHttp3Downloader with okHttpClient
OkHttp3Downloader okHttpDownloader = new OkHttp3Downloader(okHttpClient);
//Create picasso instance
picasso = new Picasso.Builder(this).downloader(okHttpDownloader).build();
//load image in imageview 'img'
picasso.load("image url").into(img);
You can use 'ETag' instead of 'if-modified-since'.
Known issue : images are not getting loaded when device is offline. Please load it from cache forcefully.
I'm just learning Retrofit and OKHttp, now I have an issue.
Every request in my app is POST, just like this:
#FormUrlEncoded
#POST("some url")
Observable<Result> getData(#Field("id") String id);
In every POST, there are two same params. So in a most simple way, I can add two more #Field in every method, for example, #Field("token"),#Field("account"). But I think there must be a smart way.
Then I thought OkHttpClient may solve this.
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
RequestBody body = new FormBody.Builder().add("account", "me")
.add("token", "123456").build();
request = request.newBuilder().post(body).build();
return chain.proceed(request);
}
}).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("some base url")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
Or
HttpUrl url = request.url().newBuilder()
.setEncodedQueryParameter("account", "me")
.setEncodedQueryParameter("token", "123456")
.build();
The first method just replace all Field to these two.
The second method just add these two as GET parameters, not POST.
Now I have absolutely no idea how to make this work.
OK...Finally I find a way to do this. But I'm not sure this is the best way.
Here is the code:
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
FormBody.Builder bodyBuilder = new FormBody.Builder();
FormBody b = (FormBody) request.body();
for (int i=0;i<b.size();i++) {
bodyBuilder.addEncoded(b.name(i),b.value(i));
}
bodyBuilder.addEncoded("account", "me").add("token", "123456");
request = request.newBuilder().post(bodyBuilder.build()).build();
return chain.proceed(request);
}
}).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://some url)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
I get all the #Field from retrofit, then add every key-value params to a new RequestBody, same as these two default params. Now every POST request has "account" and "token".
If there is a better way to do this, please let me know.
You can do that by adding a new request interceptor to the OkHttpClient. Intercept the actual request and get the HttpUrl. The http url is required to add query parameters since it will change the previously generated request url by appending the query parameter name and its value.
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("apikey", "your-actual-api-key")
.build();
// Request customization: add request headers
Request.Builder requestBuilder = original.newBuilder()
.url(url);
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
My API having some verification mechanism for every HTTP request. One of the end-point have the functionality to load a image using HTTP post method. The post request body will contain a JSON object which is verified from the server side.
For that i need to include a JSON like this on the http post request body.
{
"session_id": "someId",
"image_id": "some_id"
}
how can I do this with Picasso ?
I got the solution from the hint given by Mr.Jackson Chengalai.
Create a Okhttp request interceptor
private static class PicassoInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
Map<String, String> map = new HashMap<String, String>();
map.put("session_id", session_id);
map.put("image", image);
String requestJsonBody = new Gson().toJson(map);
RequestBody body = RequestBody.create(JSON, requestStringBody);
final Request original = chain.request();
final Request.Builder requestBuilder = original.newBuilder()
.url(url)
.post(body);
return chain.proceed(requestBuilder.build());
}
}
Create a Okhttp client add this interceptor
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.interceptors().add(new PicassoInterceptor());
Create a Dowloader using this okhttp client
OkHttpDownloader = downloader = new OkHttpDownloader(okHttpClient)
Build Picasso using this downloader
Picasso picasso = new Picasso.Builder(context).downloader(downloader ).build();
I'm using Retrofit library version 2 with OkHttpClient.
I want to get some header from all responses.
I found one solution with OkClient:
public class InterceptingOkClient extends OkClient{
public InterceptingOkClient()
{
}
public InterceptingOkClient(OkHttpClient client)
{
super(client);
}
#Override
public Response execute(Request request) throws IOException
{
Response response = super.execute(request);
for (Header header : response.getHeaders())
{
// do something with header
}
return response;
}
}
But how i can do this if i'm using OkHttpClient?
Yes, this is old question.. but still found to answer because myself too was searching similar one.
okHttpClient.interceptors().add(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", "auth-value"); // <-- this is the important line, to add new header - replaces value with same header name.
Request request = requestBuilder.build();
Response response = chain.proceed(request);
Headers allHeaders = response.headers();
String headerValue = allHeaders.get("headerName");
return response;
}
});
Hope, this helps!
P.S: no error handled.
You can use the logging interceptor for that. Add it as an interceptor to your OkHttpClient builder while building the client, set the log level and voila! You will have all the information regarding the request as well as the response.
Here's how you can add the interceptor -
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpBuilder.addInterceptor(loggingInterceptor);
client = okHttpBuilder.build();
There are four options when it comes to what you want to Log - NONE,BASIC,HEADERS, and BODY.
Now build the the retrofit instance with the above defined client and you will have all the data you need.
I have been looking at the examples in OkHttp for android and I notice there are 2 methods defined, one is called "run" and the other "post" but they never seem to be called. Is something responsible for calling these? How are they called.
Or are these just standard methods, shown as an example that I can change ?
Here is a snippet from the example, obviously i don't understand it fully as they look like "stray" methods, nobody is calling them
here is the "run"
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
and the other snippet here is the "post", i don't see any reference to it
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
Can anyone explain the reasonning behind it ?
thanks.
These are the methods, which will perform the request on the given URL.
You just need to call them like this:
OkHttpClient client = new OkHttpClient();
String run(String url) throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
String response = run("http://www.url.com");
Also, you can change their name, to anything. It doesn't matter.
The most important part of this code is:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
And you can play with the response object for getting the responseCode, responseBody, Headers etc.