I am trying to send the converted file (Base64 - String) as a parameter in POST, the file is about 8 MB, but sending takes about 4 minutes. Is there a way to speed up?
Interface:
#FormUrlEncoded
#POST("upload")
Call<Upload> upload(#Field("CONTENT") String content);
Retrofit instance:
public class RetrofitClientInstance {
private static Retrofit retrofit;
private static OkHttpClient client;
public static Retrofit getRetrofitInstance(String url) {
if (retrofit == null && !url.isEmpty()) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(url)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}}
Call:
private void upload(){
Api api = RetrofitClientInstance.getRetrofitInstance(SharedUtils.SERVER_URL).create(Api.class);
Call<Upload> request = api.upload(getBase64FromFile());
request.enqueue(new Callback<Upload>() {
#Override
public void onResponse(Call<Upload> call, Response<Upload> response) {
}
#Override
public void onFailure(Call<Upload> call, Throwable t) {
}
});
}
Try to compress your file or image before uploading, because it would take so much time to make it done
First of all, you are using enqueue() method of retrofit which is an asynchronous way of executing the code and you have registered callbacks to these methods on successful execution you will receive the call inside onResponse() method but on failure, you will get control inside the onFailure() method.
This will spawn a thread of execution from the daemon thread which creates another thread of execution you may never know when will this thread gets executed based on OS priority.
Use execute() method to execute this in a synchronous manner and then check the response time it would give a proper result.
Related
In my app I use Retrofit2 with a service to collect data on eBay. For this I need a token that is valid for 2 hours.
If I start the query, the token is taken over from my database and works. If the 2 hours have expired, the token will be re-entered in the database. But when the data is picked up again on Ebay, I get an error 401 - unauthorized access. I use a MainActivity and invite the fragments there. As soon as I restart the app, everything works again. I suspect that the service does not update the token when query and use the old token. How can I end the service or query and start with the new token? What could be the problem?
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl, String token) {
if (retrofit == null) {
String auth = "Bearer " + token;
String cont = "application/json";
OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder();
okHttpClient.addInterceptor(chain -> {
Request request = chain.request().newBuilder()
.addHeader("Authorization", auth)
.addHeader("Content-Type", cont)
.build();
return chain.proceed(request);
});
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient.build())
.build();
}
return retrofit;
}
When picking up the token from the database, according to log, the current token is always read out. But the feedback from eBay is always the 401 error.
Edit: The OkHttp connection keeps the token. Since the same address is called up, the previous connection with the old token is used. How can I replace/replace the token?
Your method has the below logic:
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl, String token) {
if (retrofit == null) {
// ...
}
return retrofit;
}
Because retrofit is defined as static it will keep its given value from the moment it's first assigned / even without the static keyword it would keep that value for the duration of the instantiated object's lifetime.
The first time getClient is called the value is null, so the logic in the if block is run & the retrofit gets defined with an Authorization header which includes the given token value.
However, subsequent calls to getClient will see that retrofit is already assigned, so will just return it; regardless of what parameters were sent to the method (i.e. even if there's a new token), and as the variable is static this will be true even if you've created a new instance of your RetrofitClient.
There are various solutions:
Remove the if statement so that the logic within it is run every time. This will incur some performance overhead (i.e. as you're having to do work for every request, even if the baseUrl and token values are the same as previously), but will return a Retrofit instance with the correct values every time. If doing this, you may not need the private static Retrofit retrofit = null; line at all; as the value is created and returned entirely within your getClient method; so making the value accessible outside of this context just adds risk.
Remove the static keyword and create a new instance of the RetrofitClient class for each new baseUrl + token value (i.e. each time your token expires). This may require additional refactoring, as you'll then require an instance of your class to access the getClient method.
Add code such as below, to check if the values are different to previous requests and update retrofit only when required. E.g.
private static Retrofit retrofit = null;
private static String baseUrlCached = null;
private static String tokenCached = null;
public static Retrofit getClient(String baseUrl, String token) {
if (retrofit == null || (baseUrl != baseUrlCached || token != tokenCached)) {
// ...
}
return retrofit;
}
I really need help!
I have a server that sends me predicting time. I need to send request to the server every 10 minutes(even if the app closed) and ask the current time. if the time changed I need to make a notification to the client.
the stop trigger is if the predicting time is now.
so - I have ClientActivity and I have the code to communicate the server.
How can I do that?
Thanks a lot!
public interface APIClient {
#POST("/api/post_some_data")
Call<PostResponse> getPostRequest(#Body PostRequest body);
}
public class NetworkClient {
public static final String BASE_URL = "http://*****:8080";
public static Retrofit retrofit;
/*
This public static method will return Retrofit client
anywhere in the appplication
*/
public static Retrofit getRetrofitClient() {
//If condition to ensure we don't create multiple retrofit instances in a single application
if (retrofit == null) {
//Defining the Retrofit using Builder
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL) //This is the only mandatory call on Builder object.
.addConverterFactory(GsonConverterFactory.create()) // Convertor library used to convert response into POJO
.build();
}
return retrofit;
}
}
I have an HTTP request inside of a method and i'm trying to return true/false based on the response from the request. im not sure what im doing wrong, I thought it was pretty straight forward. in the test scenario the condition inside of the onResponse call returns true. not sure whats getting lost in translation.
Also, in the final condition, the "message" variable is purple, in android studio, im not sure what this indicates. I think its related to my issue. suggestions?
public class DeleteButtonChecker {
public String message = new String();
public Boolean doCheck(int userID, int postID){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
Gson gson = new GsonBuilder()
.setLenient()
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
RequestInterface requestInterface = retrofit.create(RequestInterface.class);
Call<ServerResponse> response = requestInterface.check(postID, userID);
response.enqueue(new Callback<ServerResponse>() {
#Override
public void onResponse(Call<ServerResponse> call, Response<ServerResponse> response) {
ServerResponse resp = response.body();
if(resp.getResult().equals(Constants.SUCCESS)){
message = "true";
} else {
message = "false";
}
}
#Override
public void onFailure(Call<ServerResponse> call, Throwable t) {
}
});
if(message.equals("true")) {
return true;
} else{
return false;
}
}
}
The response is handled asynchronously. On the line:
response.enqueue(new Callback<ServerResponse>() {
...
You are simply giving a callback to be executed once the response is returned. However the method is not blocked and continues to the next statement - which is the:
if(message.equals("true")) {
Which can be translated to:
if("".equals("true")) {
An asynchronous request cannot be treated as a synchronous call, that is given your conditions.
If it was for me I would use RxJava 2 Single with Retrofit to return a usable result from the request.
Check this out: https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava2
And make sure to learn some RxJava which can help you on the road
How to call multiple requests at the same time in Retrofit 2
I have 2 different api, and I want to call them at the same time. How can I do this ?
Thanks!
You could use enqueue method of retrofit2 for asynchronously calling multiple request at the same time.
Here is the documentation for the enqueue:
/**
* Asynchronously send the request and notify {#code callback} of its response or if an error
* occurred talking to the server, creating the request, or processing the response.
*/
void enqueue(Callback callback);
Here is the pseudo code how you could do that:
Call<MyResponse> call = retroService.getSomeData();
call.enqueue(new Callback<MyResponse>() {
#Override
public void onResponse(
public void onFailure(
});
Just create an observer that pass parameters of the two servers.
Help the code below
OkHttpClient okHttpClient = new OkHttpClient().newBuilder().addInterceptor(new Interceptor() {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Request.Builder builder = originalRequest.newBuilder().header("Authorization",
Credentials.basic("aUsername", "aPassword"));
Request newRequest = builder.build();
return chain.proceed(newRequest);
}
}).build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://api.example.com")
.client(okHttpClient)
.build();
Font
I am just now learning about Retrofit 2. In my app Intent "UploadToServer"
I have three async tasks that I need to call sequentially:
1. Post UserName and get back UserId.
2. Post Geolocation and some other string data and get back a "report ticket number".
3. Post a jpg image along with the ticket number.
I have a web service running on my server.
In standard hand-coded Java I would use a looper or something equivalent.
How could this be accomplished using Retrofit 2? And oh, I would like to have a progress bar moving, especially when uploading the jpg image file.
Thanks.
You can chain the calls using the callbacks:
OkHttpClient client = new OkHttpClient.Builder().build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL_WEBAPI)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
mService = retrofit.create(IWebApi.class);
...
mService.first_operation(...params...).enqueue(callback);
callback is an instance of a class that expects the results of first_operation. If first_operation success, then call the second_method.
public class Example implements Callback<void> {
#Override
public void onResponse(Response<LoginResponse> response) {
second_method();
}
#Override
public void onFailure(Throwable t) {
t.printStackTrace();
}
}
Hope it helps.
Edit:
I use a ProgressDialog with indeterminated in true. You can show it right before the call to the service and hide when a response arrives, in the onResponse or in the onFailure methods.
mProgressDialog = ProgressDialog.show(this, getString(R.string.wait_plaease),
getString(R.string.executing_action), true);