Problems Downloading PDF FIle with okhttp3 and retrofit - android

My android application consume a service that returns a PDF file that contains certain data of the user, the problem is that when the service takes more than 5 seconds without responding the connection closes but the request is still open so new connections are made and then a timeout exception is launched.
if the response takes less than 5 seconds everything is ok.
this is a capture of the petition observed with charles made in the app.
I'm using okhttp3 and retrofit. this is how i build the client
val builder = OkHttpClient.Builder()
.readTimeout(1, TimeUnit.MINUTES)
.connectTimeout(1, TimeUnit.MINUTES)
.writeTimeout(1, TimeUnit.MINUTES)
.authenticator(tokenAuthenticator)
.addInterceptor(HeaderInterceptor(dataProvider))
I think the problem is about sockets or something but i cant find anything about it.

Related

Android: Not allow spam requests being called using Retrofit2

I have a case where some users end up in a loop of requesting #GET API call too often.
Too often = 10-20x every second.
Currently, I've not located the problem and it seems that it's not going to be an easy fix, but I was wondering, is there a possibility to set some kind of limitations on Retrofit2, where if the app goes into some kind of loop where single API request is called so many times, it actually ignores these requests, for instance, do 1-5x same requests in a second max. or something similar?
How could this be done (from a networking library settings perspective)? (Till I find the root cause, I'd like to protect backend)
According the this answer you can use dispatcher as below:
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(1);
OkHttpClient client = new OkHttpClient.Builder()
.dispatcher(dispatcher)
.build()
After then you will be able to send one request on a time.

How to avoid write timer resetting in OkHttpClient in retrofit 2

I am trying upload multiple photos to server. For fast upload, I am compressing photos before upload. So After this, uploading is super fast when I am connected with Wifi. But in mobile data, taking 5 to 6 minutes. So Searched a bit and found the problem. In OkHttpClient I am setting write time out for 60 seconds. This write time is out getting resetted after one byte transfer to server. So its taking more time for more bytes. How to solve it.
This is the site where I learned about Time outs in Okhttp,
https://futurestud.io/tutorials/retrofit-2-customize-network-timeouts
---> I think of using CountDownTimer after making a retrofit call. So if timer is over then I need to show alert as failed or retry. But I doen't know where to use it.
So anybody give me better solution for this.
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(60, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.build();
OkHttpClient okHttpClient = builder.build();

Retrofit one api call at a time

I have a server that support 1 api call at a time, i have tried adding Dispatcher to my retrofit Okhttp client like this:
Dispatcher dispatcher = new Dispatcher();
dispatcher.setMaxRequests(1);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder()
.connectTimeout(20, TimeUnit.SECONDS)
.writeTimeout(60, TimeUnit.SECONDS)
.readTimeout(2, TimeUnit.MINUTES)
.dispatcher(dispatcher);
but that did not worked as expected ,
Dispatcher enqueue api calls connections and does not wait for
response but i want to wait for one api call response and then start
a next one
In the meantime during one api call next one if requested should wait before the first api call give reponses.
What can be done in this case, Any suggestions ?
Maybe you can send requests via execute method of Retrofit. See this

Does creating new object for Retrofit slows the service response time?

I have used retrofit creating new objects each time I use a webservice . The webservice response time is good . But when tried within the app it slows down.
Does this effect the response?
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiConstants.BASE_URL)
.addCallAdapterFactory(new ErrorCallback.ErrorHandlingCallAdapterFactory())
.addConverterFactory(GsonConverterFactory.create())
.build();
In the Retrofit documentation the build, baseUrl, addCallAdapterFactory, addConverterFactory operations dont entablish any connections. This make sense because they are used just to prepare the Retrofit instance for communication.
Also, considering that restful servicies typically use HTTP for communication, there is no need to entablish a connection per session. The connection entablishes every time you call an operation of the webservice api.
So, creating the instance everytime will no affect in terms of communication, but it will affect the client cpu and memory resources unnecessary.
Creating a new Retrofit instance does affect the response time and I can confirm this by my own recent experience. If I created new instance for each request the response time that I was getting was >= 1700ms where as when I used single instance for API calls, I got response in <= 500 ms.

Simultaneous async requests with OkHttp

My app is using long polling to keep some local state up to date, but it also needs to communicate with the server while independently/simultaneously maintaining the long-polling connection.
The trouble is, OkHttp blocks any other calls to the server while it waits for the long-polling connection to receive data or timeout.
I've set up two OkHttpClient instances, one for normal API calls to the server, and the other to maintain the long-polling connection.
private static OkHttpClient client = new OkHttpClient();
private static OkHttpClient longPollingClient = new OkHttpClient();
I've tried having the long polling client set its own connection pool (separate from the default, shared connection pool )
ConnectionPool connectionPool = new ConnectionPool(
LONG_POLL_CLIENT_CONNECTION_POOL_MAX_CONNECTIONS, // 5
LONG_POLL_CLIENT_CONNECTION_POOL_KEEP_ALIVE_DURATION_MILLIS // 5 mins
);
longPollingClient.setConnectionPool(connectionPool);
I've also futzed with its dispatcher:
longPollingClient.getDispatcher().setMaxRequests(5);
longPollingClient.getDispatcher().setMaxRequestsPerHost(5);
But no matter what, calls on the vanilla client are blocked by the longPollingClient
Note, I'm using separate AsyncTasks for my calls. Does AsyncTask share a single thread in a thread pool? I'm relatively new to Android, so I'm not certain.

Categories

Resources