I've setup retrofit 2.1 and it is not making calls to my api at all. I just setup a lamp stack and made my ip publicly accessible. I'm trying to send information via a POST to my php script which would add data to my db. For some reason, retrofit will not make the call to my api... I'm not sure what I'm doing wrong.
#POST("/sendInformation.php")
Call<JSONObject> sendUserInfo(#Body JSONObject userViewModel);
OkHttpClient.Builder client = new OkHttpClient.Builder();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> Log.d(TAG, message));
logging.setLevel(HttpLoggingInterceptor.Level.BASIC);
client.addInterceptor(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client.build())
.addConverterFactory(JacksonConverterFactory.create())
.build();
UserInformationService userService = retrofit.create(UserInformationService.class);
Call<JSONObject> call = userService.sendUserInfo(jsonObject);
call.enqueue(new Callback<JSONObject>() {
#Override
public void onResponse(Call<JSONObject> call, Response<JSONObject> response) {
Toast.makeText(HomeActivity.this, response.body().toString(), Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<JSONObject> call, Throwable t) {
}
});
I tried to add logging but it won't make the call so I can't even see the logging. Anyone have any ideas?
EDIT: The BASE_URL I'm using is my public IP. I just forwarded my ports so it's accessible. I tried doing a POST on hurl.it and it works fine. It's only retrofit not working. I've also tried this with an asyncTask and httpURLConnection and it also works. I must be missing something really minor...
Call<JSONObject> call = userService.sendUserInfo(jsonObject);
This line is not enough. The Call<T> object represents an 'intent' of a call rather than the operation itself, and you need to execute it by calling one of two methods on the object: execute and enqueue.
Execute works in a blocking manner and will return your JSONObject through the response.getBody() method:
Response<JSONObject> response = call.execute();
Enqueue works asynchronously and will provide your JSONObject through the callback object - if call is successful, onResponse method will be called with your response as a call parameter.
call.enqueue(new Callback<JSONObject>() {
#Override
public void onResponse(Call<JSONObject> call, Response<JSONObject> response) {
}
#Override
public void onFailure(Call<JSONObject> call, Throwable t) {
}
});
Related
Imagine this scenario:
I start a requestA using the Call.enqueue() method, then, before requestA be finished, I start requestB at the same endpoint of requestA. While I'm using Call.enqueue() method, requestB will be executed after requestA? Or enqueue() method is just used to do requests asynchronously?
I search that information at docs and here on StackOverflow but all the information is superficial about this specific method.
Here is my code - this same code is used for both requests:
foolRequest.enqueue(new Callback<Response>() {
#Override
public void onResponse(#NonNull Call<Response> call,
#NonNull retrofit2.Response<Response> response) {
//do something
}
#Override
public void onFailure(#NonNull Call<Response> call,
#NonNull Throwable t) {
//do something
}
});
I think so,
Otherwise, if you implement your own connection client.
By the source code from OkHttpClient, there is a dispatcher class, save all the enqueue API, and it uses queue to save the relative task
synchronized void enqueue(AsyncCall call) {
if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
runningAsyncCalls.add(call);
executorService().execute(call);
} else {
readyAsyncCalls.add(call);
}
}
I have something like this
Retrofit retrofit =new retrofit2.Retrofit.Builder()
.baseUrl("URL")
.addConverterFactory(GsonConverterFactory.create())
.build();
requestService = retrofit.create(RequestInterface.class);
call = requestService.getData(page);
call.enqueue(new Callback<List<Cats>>() {
#Override
public void onResponse(Call<List<Cats>> call, Response<List<Cats>> response) {
....
}
#Override
public void onFailure(Call<List<Cats>> call, Throwable t) {
...
}
});
However when i want to get the second page, when i make a request for the second page within the same class, retrofit callback methods is not getting called.
call = requestService.getData(page); // page incremnted
call and requestService is globally defined
in Retrofit, each "call" instance is linked to one API call (single network request) and cannot be reused. You can reuse your RetrofitSerive instance, but for every new API call you will have to create a new Call object and enqueue it separately
You can use a generic response and use an url each time.
#GET
Call<Generic<T>> getUsers(#Url String url);
Im making an asynchronous call and im able to send a request to the server and getting my desired JSON(using postman) but for some reason the OnResponse and OnFailure methods are not being executed, may you please help me if im missing out something.Im using retrofit2
private List<Advert> getAdverts(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl( "http://192.168.100.4:8092/portal/")
.client(client.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
RequestService requestService = retrofit.create(RequestService.class);
Call<List<Advert>> customerCall= requestService.getAdverts(accountNumber);
System.out.println("++++++++++++++ request was made +++++++++++++++++++");
customerCall.enqueue(new Callback<List<Advert>>() {
#Override
public void onResponse(Call<List<Advert>> call, Response<List<Advert>> response) {
Log.d("onResponse", "" + response.message());
System.out.println("++++++++++++++ was here+++++++++++++++++++");
if (response.isSuccessful()) {
adverts.addAll(response.body());
} else {
Toast.makeText(getContext(), "" + response.message(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(Call<List<Advert>> call, Throwable t) {
Log.d("onFailure", t.toString());
}
});
return adverts;
}
Not sure, but you're returning before de operation has ended (as you mentioned is a asynchronous call). So as soon you enqueue, you're returning "adverts" (probably cancelling your call).
Consider using other alternatives to return your response, like Callbacks, EventBus, persist the response on local storage, etc.
There are several questions on stackoverflow that are just like mine, but I haven't been able to solve my issue. The error is as stated in the title. I'm working with the Spotify API to get the current user's profile. I feel like I have a fundamental misunderstanding with what's going on.
Here's what I have in my main activity:
Gson gson1 = new GsonBuilder()
.setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
.setLenient()
.create();
Retrofit retrofit1 = new Retrofit.Builder()
.baseUrl(ENDPOINT_ACCOUNTS)
.addConverterFactory(GsonConverterFactory.create(gson1))
.build();
SpotifyAPI spotifyAPI = retrofit1.create(SpotifyAPI.class);
Call<User> call1 = spotifyAPI.getUserData("Authorization: Bearer " + sp.getString("accessCode", "DEFAULT"));
call1.enqueue(new Callback<User> () {
#Override
public void onResponse(Call<User> call, Response<User> response) {
...
}
#Override
public void onFailure(Call call, Throwable t) {
...
}
});
Here is my interface:
String ENDPOINT_V1 = "https://api.spotify.com/";
#GET("/v1/me")
Call<User> getUserData(#Header("Authorization") String authorization);
And here is my User class:
public class User {
String id;
public String toString() {
return(id);
}
}
OnFailure() is being triggered, spitting out the error message in the title. If I substitute all instances of User with ResponseBody, the call succeeds with a status code of 200. But the contents of response is not at all what I want. Please let me know if there is more information I can provide. Thank you.
Turns out my base URL was wrong. Works like a charm now. Thanks for looking this through.
I want to pass Header and Body dynamically to a Web Api. So, I have implemented as below:
public interface NotificationService {
#POST("user/update/notification")
Call<JsonObject> notification(#Header("Authorization") String authorization, #Body NotificationRequest notificationRequest);
}
And using this as,
showProgressDialog();
NotificationRequest notificationRequest = new NotificationRequest(checked ? ApiConstants.IS_ON : ApiConstants.IS_OFF, getUserId());
NotificationService notificationService = ApiFactory.provideNotificationService();
Call<JsonObject> call = notificationService.notification(getAuthorizationHeader(), notificationRequest);
call.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
logDebug(SettingsFragment.class, response.body().toString());
hideProgressDialog();
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
hideProgressDialog();
}
});
But this way, I am not getting null response (response.body() is null).
Can anyone suggest how to pass Dynamic Header and Body together ?
Note: I went through this tutorial but didn't found the way to pass both.
As far as I can see, there is no way to pass both Header and Body at the same time.
But You can add Interceptor into OkHttpClient as below:
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.cache(cache);
builder.addInterceptor(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request.Builder ongoing = chain.request().newBuilder();
ongoing.addHeader("Authorization", getToken(app));
return chain.proceed(ongoing.build());
}
});
This will add authorization header in every request. You can control adding header to some condition like if User is logged in, only then request header should be added.
Just wrap below line in if condition to something like:
if(isUserLoggedIn())
ongoing.addHeader("Authorization", getToken(app));
You are using Retrofit2. It is completely possible using dynamic headers for example:
#POST("hello-world")
fun getKaboom(
#Body body: TheBody,
#Header("hello-world-header") helloWorldHeader: String? = "kaboom"
): Single<KaboomResponse>