Retrofit enqueue doesn't work but execute work - java

I'm using com.squareup.retrofit2:retrofit:2.2.0
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://localhost:9000")
.addConverterFactory(GsonConverterFactory.create())
.client(httpClient.build())
.build();
final UserService service = retrofit.create(UserService.class);
Call<User> userCall = service.createUser(user)
Here is the problem: when I run the execute it make REST API request but when I use enqueue it does nothing (no exception, no log)
userCall.execute(); //this work
//this does not work
userCall.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
// no response
}
#Override
public void onFailure(Call<User> call, Throwable t) {
//nothing here
}
});

Well,
The issue was because I was using an emulator and try to call the localhost however, it turn out if you want call the localhost you have to use this ip 10.0.2.2
The execute works because I was running as unit test but when it runs enqueue I think it need to run on android platform.
refer to this
https://developer.android.com/studio/run/emulator.html#networkaddresses
How to get the Android Emulator's IP address?

You can try this full Answer Link
Here is the shortest code snippest.
private void emailLoginRequest() {
LoginService loginService = ApiFactory.createService(LoginService.class);
Call<JsonObject> call = loginService.login(edtEmail.getText().toString(),edtPassword.getText().toString(),mDeviceType,mDeviceToken);
call.enqueue(new Callback<JsonObject>() {
#Override
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
hideProgressDialog();
if (response.isSuccessful()) {
LOGD(TAG, "onResponse 0: " + response.body().toString());
LoginResponse loginResponse = new Gson().fromJson(response.body().toString(), LoginResponse.class);
System.out.println("+++ get message >> " + loginResponse.getMessage());
int status = loginResponse.getStatus();
}else {
LOGD(TAG, "response fail 0: " + response.body());
}
}
#Override
public void onFailure(Call<JsonObject> call, Throwable t) {
hideProgressDialog();
LOGD(TAG, "onFailure: " + t.getMessage());
}
});
}

put your code as this:
userCall.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
Toast.makeText(this, "in response", Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<User> call, Throwable t) {
Toast.makeText(this, "in response", Toast.LENGTH_SHORT).show();
}
});
Now based on method call you will get toast if its in response toast will be "In response" don't forget write youractivity name before this like : MainActivity.this

see this
retrofit can be called by 2 methods separately one is synchronous and another way is asynchronous.
enqueue is an asynchronous way where it does not wait for a response and proceed. here you need to handle Call separately to load UI later.
Execute is asynchronously call rest api and wait until get response and process it.
choice wisely

Related

How to handle Call<Object> Response as String?

Im in a confusing spot right now. My API returns a Token for Login when posting a new User with UserData. How do I get the response.body() as a String to save it?
It only returns a Post object what I don't actually want. I only use it to create the Post.
private void createPost(User user) {
Post post = new Post(user.getName(), user.getGender(), user.getBirthyear(), user.getHeight(),user.getWeight());
Call<Post> call = jsonmongo.createPost(post);
// To execute it asynchron
call.enqueue(new Callback<Post>() {
#Override
public void onResponse(Call<Post> call, Response<Post> response) {
if (!response.isSuccessful()) {
Log.e("RESPONSECODE", ""+ response.code());
return;
}
Log.e("RESPONSECODE", ""+ response.code());
}
#Override
public void onFailure(Call<Post> call, Throwable t) {
Log.e("RESPONSECODE", ""+ t.getMessage());
}
});
}
Get Response.Body and save it to the Database via SQL Adapter ( adapter.addToken(response.body()) )
response.body().toString only returns Object reference ( com.example.Resources.Post#4c8352 )
String S = new Gson().toJson(response.body())
Log.e("JSON", S)
Returns this:
E/JSON: {"age":0,"gender":0,"height":0,"weight":0}
Wanted output:
E/JSON: {"token":aslfjkhr9RRRRf283FGr3489pjfGGG34HH89fj}
let me try... you can use Gson library to create a String json object from the response.
Try it:
new Gson().toJson(response);

Android - Display loading bar when calling API with retrofit

In my app i am using retrofit 2 to retrieve data from a API. I have no problem about this. The problem is that i want to display a loading bar while this execution. The code is this
Call<MainInvestorProducts> call = apiInterface.getUseraccounts("Bearer "+bearerToken);
mkLoader.setVisibility(View.VISIBLE);
call.enqueue(new Callback<MainInvestorProducts>() {
#Override
public void onResponse(Call<MainInvestorProducts> call, Response<MainInvestorProducts> response) {
// If success response set the textViews
if (response.code() == 200) {
retrievedData = response.body();
//else display error message
}else if (response.code() == 401) {
Toasty.error(getApplicationContext(), getString(R.string.expired_token),Toasty.LENGTH_LONG).show();
finish();
}
}
#Override
public void onFailure(Call<MainInvestorProducts> call, Throwable t) {
}
});
mkLoader.setVisibility(View.GONE);
The problem is that mkloader is never show up.
My APIClient code
public class APIClient {
public static Retrofit retrofit = null;
public static Retrofit getClient(){
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
retrofit = new Retrofit.Builder()
.baseUrl("https://api-test01.moneyboxapp.com")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
return retrofit;
}
}
And this is an example of the Interface
#Headers({
"AppId: 3a97b932a9d449c981b595",
"Content-Type: application/json",
"appVersion: 5.10.0",
"apiVersion: 3.0.0"
})
#POST("/users/login")
Call<MainUserLogin> logInUser(#Body LoginBody loginBody);
Before calling the api you should start showing the loader (be sure that the api call is going to happen) and when once completed dismiss that
mkLoader.setVisibility(View.VISIBLE);
Call<MainInvestorProducts> call = apiInterface.getUseraccounts("Bearer "+bearerToken);
call.enqueue(new Callback<MainInvestorProducts>() {
#Override
public void onResponse(Call<MainInvestorProducts> call, Response<MainInvestorProducts> response) {
// If success response set the textViews
if (response.code() == 200) {
retrievedData = response.body();
//else display error message
}else if (response.code() == 401) {
Toasty.error(getApplicationContext(), getString(R.string.expired_token),Toasty.LENGTH_LONG).show();
finish();
}
}
#Override
public void onFailure(Call<MainInvestorProducts> call, Throwable t) {
mkLoader.setVisibility(View.GONE);
}
});
you just need to make the loader visibility to VISIBLE before calling the API and in case the api is succes or failure you set visibility to GONE

Proxy Authentication Required, Retrofit

Getting this error when make api call in retrofit
Response{protocol=http/1.1, code=407, message=Proxy Authentication
Required, url=http://example.com/test.xml}
below was my api call.
private void showProxies() {
serviceCall = apiService.listOfServers();
serviceCall.enqueue(new Callback<ServerListModel>() {
#Override
public void onResponse(Call<ServerListModel> call, Response<ServerListModel> response) {
if (response.body() != null) {
ArrayList<Proxies> proxyArrayList = response.body().proxiesArrayList;
showProxyDialog(proxyArrayList);
}
else
Toast.makeText(BrowserActivity.this, "Server 407 error.", Toast.LENGTH_SHORT).show();
}
#SuppressLint("LongLogTag")
#Override
public void onFailure(Call<ServerListModel> call, Throwable t) {
Log.e(TAG, t.toString());
}
});
}
you have add proxy to you Retrofit object
java.net.Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
OkHttpClient client = new OkHttpClient.Builder().proxy(proxy).build();
Retrofit.Builder builder = new Retrofit.Builder().client(client);
Retrofit retrofit = builder.build();
In my case, I was connected to the proxy network this issue is not related to retrofit.

How to return network data fetched in another class back into Android MainActivity?

In MainActivity onCreate I invoke network class to handle request using okhttp3. I need return data from network class to use further in logic in MainActivity, the calling class. In debugging, return data from network class is correct, but when I want use return data in another expression in MainActivity the return data give null.
//In MainActivity
Network n = new Network();
n.network("baseLogic", "user", params);
if(n.resp == null){
String resp = n.resp;
Toast toast = Toast.makeText(getApplicationContext(), resp, Toast.LENGTH_SHORT);
toast.show();
}else if (n.resp.equals("0")) {
Intent intent = new Intent(MainActivity.this, Rei.class);
intent.putExtra(EXTRA_MESSAGE, message);
startActivity(intent);
}
Below is the network classes called from within MainActivity.
We've built a URL from passed params.
The return is stored in a class variable on response then returned by the class.
public class Network(){
public String resp;
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
//resp = client.newCall(request).execute().body().toString();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(okhttp3.Call call, IOException e) {
}
#Override
public void onResponse(okhttp3.Call call, Response response) throws IOException {
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
resp = response.body().string();
response.close();
}
});
return resp;
}
Debugging shows value difference
Attempted solutions:
1) I tried to find a method or process (android splashscreen) to pause the MainActivity thread so the Network class instance can return data for MainActivity on time.
2) Spinning off network class instance on a task or asyncTask.
Please help

Post request with query params and body

I am making use of Retrofit to call the restful webservices in the android, I have come across the scenario like I need to pass query params and request payload object in the retrofit request, so I've tried something like this
#POST("actual url")
Call<ReceiptList> getData(#Query("limit") String limit,
#Query("page") String page,
#Body ReceiptRequestPayload receiptRequestPayload);
Calling API
Call<cutomObject> responseCall = API.getData("10", "1", requestPayload);
responseCall .enqueue(new Callback<cutomObject>() {
#Override
public void onResponse(Call<cutomObject> call, retrofit2.Response<cutomObject> response) {
Log.d(TAG, "onResponse: Receipts"+response);
Log.d(TAG, "onResponse: Receipts"+response.body());
}
#Override
public void onFailure(Call<ReceiptList> call, Throwable t) {
}
});
But it's not working.
Thanks in advance
Use OkHttp Logging Interceptor to log your HTTP request and response data

Categories