Add Response call back when using retrofit with rxjava - android

I am using retrofit with Rxjava to get response from API as you can see the method i am using i can't see what's coming in the response and offcourse i don't need to becuase i am providing GsonConverter to retrofit but for some debugging reason i need to see the response that coming from API. How can i do this, what code i need to add.
public interface ProductApiService
{
String END_POINT = "http://beta.site.com/index.php/restmob/";
#GET(Url.URL_PRODUCT_API)
Observable<Product> getProducts(#Query("some_id") String cid);
class Creator
{
public static ProductApiService getProductAPIService() {
Gson gson = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ProductApiService.END_POINT)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
return retrofit.create(ProductApiService.class);
}
}
}

You can only do this as of Retrofit 2: Change the return type to include Response:
#GET(Url.URL_PRODUCT_API)
Observable<Response<Product>> getProducts(/* ...etc... */);
You can also use Observable<Result<Product>> if you want to see all possible errors in onNext (including IOException, which normally uses onError).

Daniel Lew's approach is quick and contains the least amount of boiler plate code. However, this may force you to refactor your networking logic. Since you mention needing this for debugging purposes, perhaps using a configured OkHttpClient with Interceptors is a less intrusive strategy.
OkHttpClient httpClient = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request req = chain.request();
Response resp = chain.proceed(req);
// ... do something with response
return resp;
}
})
.build();
Retrofit retrofit = new Retrofit.Builder()
.client(httpClient)
.baseUrl(ProductApiService.END_POINT)
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();

Related

How to get intermediate response from Retrofit API call?

I using Retrofit to making API call. All API call is working fine except one where its returning huge response around 15k records.
Issue is when made call progress bar is being shown infinitely until I get response. And as response too huge getting OOM exception.
As an solution I found that need to use #Streaming annotation. I used that but didn't get intermediate callback. I want API should return chunk of response one by one.
Please help me.
public static ServiceInterface getServiceAPIClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
Gson gson = new GsonBuilder()
.setLenient()
.create();
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(
new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request request = chain.request();
Request.Builder builder = request.newBuilder();
builder = request.newBuilder();
if (!TextUtils.isEmpty(PrefsHelper.getAccessTokenEdrm())) {
builder.addHeader(AUTHORIZATION, PrefsHelper.getAccessTokenEdrm());
}
builder.addHeader(API_VERSION, "1.0")
.addHeader("Accept", "application/json");
request = builder.build();
return chain.proceed(request);
}
}).connectTimeout(5, TimeUnit.MINUTES) .readTimeout(5, TimeUnit.MINUTES).addInterceptor(interceptor)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.client(client)
.build();
return retrofit.create(ServiceInterface.class);
}
API Method
#POST(EdrmConstants.SEARCH_DOCUMENTS)
#Streaming
Observable<ResponseBody> searchDocuments(#Body DocumentRequest documentRequest);
15k records is too match.
Retrofit needs time to make http request and makes serialization to your ResponseBody.class
I sure serialization takes main time.
I guess most right solution is to edit request on server side to split data on pages with 200-500 records.

Android Retrofit Interceptor add body param for all calls

Is there any way to edit the body of a network call for adding a default attribute used in the 95% of the calls?
I've seen that a query parameter is pretty easy to add (link)
But, I have not seen it for a Body.
My problem is that I'm working with an old API that asks me to send in each request the token. So I need to add this line in most of the classes.
#SerializedName("token") val token: String
Any ideas?
You should use httpInterceptor to solve this problem if you send in header
final OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request()
.newBuilder()
// add token key on request header
// key will be using access token
.addHeader("token", yourToken)
.build();
return chain.proceed(request);
}
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
Edit : Im sorry, I've realized now you ask about sending in body.
I think it can be possible with old way(without Gson, Moshi etc). It is really more annoying than adding to every request.

Web-service call from android app takes 10 mins to reflect the latest results

Am Struggling with one of the issues of being service taking almost 10 mins to reflect the updated results. Actually, am using an API of type Get, the structure of the service is like this:
www.abc.net/wp-json/wp/v2/posts?categories=192&page=1&per_page=2
When I try to call the service from the browser it's showing the updated information, but when I try to call the same service from my android app using retrofit it's delaying the updated response by almost 10 mins.
Here is the code mentioned in my last question about the same :
public class ApiClient {
private static Retrofit retrofit = null;
public static Retrofit getClient() {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.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()
.cacheControl(CacheControl.FORCE_NETWORK)
.addHeader("Cache-Control", "no-cache")
.addHeader("Cache-Control", "no-store");
Request request = requestBuilder.build();
return chain.proceed(request);
}
});
OkHttpClient client = httpClient.build();
retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.SERVICE_ENDPOINT)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
}
}
My API Interface
public interface ApiInterface {
String SERVICE_ENDPOINT = "https://example.com/wp-json/wp/v2/";
#GET("posts")
Call<ArrayList<CategoryResponse>> fetchlatestposts(#Query("bloglist")
int bloglist);
}
What can be the issue for not getting the updates response in real time, while as after 10-15 mins of pause it will give the updated results.
The issue was from the server side, WordPress has cache enabled which was causing the issue.

Retrofit 2 - Is it possible to get the size of a JSON that I'm sending and receiving?

I need to build a traffic monitor on my Android app, and I need to have stored the size of all json that I'm sending and receiving through retrofit. Using log I can see the actual size of it, but I haven't find a way to get this information so I could save it. I can't get the response.raw either since it's already been parsed to my classes. Is there any way to achieve that?
EDIT: Marked vadkou answer as the best one.
Instead of creating a new interceptor, I passed the lamda expression:
httpClient.addInterceptor( chain -> {
okhttp3.Request request = chain.request();
okhttp3.Response response = chain.proceed(request);
if(request.body()!=null) {
long requestLength = request.body().contentLength();
Log.e("SERVICE GENERATOR", " CONTENT LENGTH" + requestLength);
}
long responseLength = response.body().contentLength();
Log.e("SERVICE GENERATOR", " RESPONSE LENGTH" + responseLength);
return response;
});
Retrofit 2 uses OkHttp internally, and you could configure OkHttp without having to resort to getting raw HTTP response as in Vaiden's answer by adding a custom Interceptor while building an adapter as follows:
private Retrofit createRetrofit() {
return new Retrofit.Builder()
.baseUrl(END_POINT)
// .addConverterFactory(...)
// .addCallAdapterFactory(...)
.client(createClient())
.build();
}
private OkHttpClient createClient() {
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
okHttpClientBuilder.addInterceptor(createYourInterceptor());
return okHttpClientBuilder.build();
}
The Interceptor interface among other things allows you to access request body for every request you make.
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
// do what you want with request.body().contentLength();
return chain.proceed(request);
}
For this you need to create custom interecptor
please reffere below example
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;
public class CustomIntercepter implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();///
Response response = chain.proceed(request);
// for request size
long requestLength = request.body().contentLength();
// for response size
long responseLength = response.body().contentLength();
return response;
}
}
`
Now Create Retrofit object
OkHttpClient provideOkHttpClient(CustomIntercepter customIntercepter) {
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();
okHttpClient.cache(cache);
okHttpClient.addInterceptor(customIntercepter);
return okHttpClient.build();
}
Retrofit provideRetrofit(Gson gson, OkHttpClient okHttpClient) {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl(SERVER_URL)
.client(okHttpClient)
.build();
return retrofit;
}
You should try accessing the raw HTTP response (Get raw HTTP response with Retrofit):
You begin with a Response object.
This object has a .raw() method that returns the actual HTTP layer's reponse,
in the form of an okhttp3.Response object. Calling .body() would give you a ResponseBody object, which encapsulates the raw response.
You can get the length of the response by calling .contentLength().

Can someone explain to me if this is a singleton object? (Android)

i'm still new with singletons. I'm trying to use the DRY methode, but i'm not sure if it's correct. Below you find the class Authorization which i use to create a OkHttpClient and Retrofit.Builder. I'm not sure if it's the right way:
public class Authorization {
private static Retrofit retrofit = null;
public static Retrofit authorize(Activity activity){
final String token = SharedPreferencesMethods.getFromSharedPreferences(activity, activity.getString(R.string.token));
OkHttpClient client = new OkHttpClient();
client.interceptors().add(new Interceptor() {
#Override
public com.squareup.okhttp.Response intercept(Chain chain) throws IOException {
Request newRequest =
chain.request().newBuilder()
.addHeader("Authorization", "Bearer " + token).build();
return chain.proceed(newRequest);
}
});
if(retrofit == null){
retrofit = new Retrofit.Builder()
//10.0.3.2 for localhost
.baseUrl("http://teamh-spring.herokuapp.com")
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
The return value of the method authorize is returning a retrofit object.
Is it a singleton?
Here i call the api
CirkelsessieAPI cirkelsessieAPI = Authorization.authorize(getActivity()).create(CirkelsessieAPI.class);
Call<List<Cirkelsessie>> call = cirkelsessieAPI.getCirkelsessies();
// more code here
Thank you!
No it's not. A singleton is a design pattern that restricts the instanciation of a class to one object. I'm sure you can see why you can instantiate more than one Authorization object, and while the class "Authorization" restricts the instanciation of the class Retrofit to one object for its attribute, it can't in any way restricts someone else from instantiating another Retrofit object somewhere else.

Categories

Resources