how to send POST using retrofit, await process and receive response JSON? - java

In my app, I send a json with information to the server, which is processed and after having a result, it returns another Json response. I don't know how to read that response Json.
this is part of code:
`
private void sendData(String tipo, String dni, String instrucciones, String video) {
progressDialog.setMessage("wait ...");
progressDialog.setCancelable(false);
progressDialog.show();
ApiInterface apiInterface = SendDeviceDetails.getRetrofit().create(ApiInterface.class);
final PostModel postModel= new PostModel(tipo, dni, instrucciones, video);
Call<PostModel> call = apiInterface.PostData(postModel);
call.enqueue(new Callback<PostModel>() {
#Override
public void onResponse(Call<PostModel> call, Response<PostModel> response) {
progressDialog.dismiss();
if (response.isSuccessful()) {
Toast.makeText(MainActivity3.this, response.body().getStatus(), Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<PostModel> call, Throwable t) {
progressDialog.dismiss();
Toast.makeText(MainActivity3.this, "error in conexion", Toast.LENGTH_SHORT).show();
}
});
`
It runs fine on submit, process, I can read the result of the service, but I don't know how to read the response json
The server sends me this json:
results JSON :{"status":"1","message":"ok","ID":"609691","NAME":"xxxxxxxxx"}

you declare model class look like this
public class PostModel {
// request
..................
........
// response
#SerializedName("status")
public String status;
#SerializedName("message")
public String message;
#SerializedName("ID")
public String ID;
#SerializedName("NAME")
public String NAME;
}
read response
PostModel postModel = response.body();
String message = postModel.message;
Toast.makeText(context, "message", Toast.LENGTH_SHORT).show();

Let's say you want to send the PostModel model as a request object and receive the PostResultModel object as a response. Then you create the interface with the method:
public interface ApiInterface {
Call<PostResultModel> postData(#Body PostModel request);
}
public class PostResultModel {
#SerializedName("status")
private String status;
#SerializedName("message")
private String message;
#SerializedName("ID")
private String id;
#SerializedName("NAME")
private String name;
// getters and setters
}
You can use this method like this:
ApiInterface apiInterface = SendDeviceDetails.getRetrofit().create(ApiInterface.class);
final PostModel postModel= new PostModel(tipo, dni, instrucciones, video);
Call<PostResultModel> call = apiInterface.postData(postModel);
call.enqueue(
new Callback<PostResultModel>() {
#Override
public void onResponse(Call<PostResultModel> call, Response<PostResultModel> response) {
if (response.isSuccessful()) {
final PostResultModel postResultModel = response.body();
// todo some logic with reponse
}
}
#Override
public void onFailure(Call<PostResultModel> call, Throwable t) {
// todo some logic when request failed
}
}
);
See this article to get more information

Related

Method always return empty list

I am using mvp Design pattern in android development and i am using retrofit2 with it ... when i run the function to get me information from a the web it get the information but returns null list
the Response.Body come with response that mean that the code works
the model function
List<SearchDdb> searchResult;
private Context context;
public MainModel(Context context){this.context=context;}
public List<SearchDdb> searchUser(String name) {
final MainPresenter presenter = new MainPresenter(context);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://jsonplaceholder.typicode.com/")
.addConverterFactory(GsonConverterFactory.create())
.build();
Db db = retrofit.create(Db.class);
Call<List<SearchDdb>> call = db.getUsers(name);
call.enqueue(new Callback<List<SearchDdb>>() {
#Override
public void onResponse(Call<List<SearchDdb>> call, Response<List<SearchDdb>> response) {
if(!response.isSuccessful()){
presenter.showDialog();
}
searchResult = response.body();
}
#Override
public void onFailure(Call<List<SearchDdb>> call, Throwable t) {
}
});
return searchResult;
}
the SearchDdb file
private int id;
private String name;
private String grade;
private String age;
private String address;
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getGrade() {
return grade;
}
public String getAge() {
return age;
}
public String getAddress() {
return address;
}
}
How i call the function
List<SearchDdb> ressult = presenter.searchUser("1");
You cant call it like List<SearchDdb> ressult = presenter.searchUser("1"); because searchUser method makes an async request via retrofit. This way searchUse returns null searchResult because response has not come yet.
Define a LiveData in your viewmodel class and observe it in your activity/fragment. When response comes from api in
onResponse in searchUser post that response to live data and use it where you observe.
If you want to see a tutorial you can look at this article.
Here is another example.

retrofit error code 404 using Multipart Post method

I want to upload two videos and some text fields into the retrofit library
using Multipart Post method, How to Send Value using the android retrofit library
API Interface
#Headers({"Accept: application/json"})
#Multipart
#POST("event")
Call<ResponsePojo> submitData(#Part MultipartBody.Part video,
#Part("device_id") String device_id,
#Part("lat") String lat,
#Part("lng") String lng,
#Part("speed") String speed,
#Part("event_type") String event_type,
#Part MultipartBody.Part videolarge);
ResponsePoja model Class
public class ResponsePojo {
#SerializedName("fileData")
#Expose
private String fileData;
#SerializedName("device_id")
#Expose
private String device_id;
#SerializedName("lat")
#Expose
private String lat;
#SerializedName("lng")
#Expose
private String lng;
#SerializedName("speed")
#Expose
private String speed;
#SerializedName("event_type")
#Expose
private String event_type;
public ResponsePojo(String fileData, String device_id, String lat, String lng, String speed, String event_type) {
this.fileData = fileData;
this.device_id = device_id;
this.lat = lat;
this.lng = lng;
this.speed = speed;
this.event_type = event_type;
}
public String getFileDatasmall() {
return fileData;
}
public void setFileDatasmall(String fileDatasmall) {
this.fileData = fileDatasmall;
}
public String getDevice_id() {
return device_id;
}
public void setDevice_id(String device_id) {
this.device_id = device_id;
}
public String getLat() {
return lat;
}
public void setLat(String lat) {
this.lat = lat;
}
public String getLng() {
return lng;
}
public void setLng(String lng) {
this.lng = lng;
}
public String getSpeed() {
return speed;
}
public void setSpeed(String speed) {
this.speed = speed;
}
public String getEvent_type() {
return event_type;
}
public void setEvent_type(String event_type) {
this.event_type = event_type;
}
Bellow Send Button Click Method ,When i click time upload all data save to server
OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(100, TimeUnit.SECONDS)
.readTimeout(100,TimeUnit.SECONDS).build();
Retrofit builder = new Retrofit.Builder()
.baseUrl(API.BaseUrl).client(client)
.addConverterFactory(GsonConverterFactory.create(new Gson())).build();
API api = builder.create(API.class);
//create file which we want to send to server.
File videoFIle = new File(String.valueOf(realUri));
RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), videoFIle);
MultipartBody.Part image = MultipartBody.Part.createFormData("fileData", videoFIle.getName(), requestBody);
Call<ResponsePojo> call = api.submitData(image, "1, ", "4.667566", "54.54448", "5457", "2",image);
call.enqueue(new Callback<ResponsePojo>() {
#Override
public void onResponse(Call<ResponsePojo> call, Response<ResponsePojo> response) {
ResponsePojo body = response.body();
Toast.makeText(getApplicationContext(), String.valueOf("Code "+response.message()), Toast.LENGTH_SHORT).show();
pd.dismiss();
}
#Override
public void onFailure(Call<ResponsePojo> call, Throwable t) {
Toast.makeText(getApplicationContext(), "File "+t.toString(), Toast.LENGTH_SHORT).show();
pd.dismiss();
}
});
Postman send request method
For this instance,a 404 means there is no API for this URL.
Maybe, your URL needs to be http://192.168.0.105/register/
instead of http://192.168.0.105/register or maybe it is malformed.
Example, http://192.168.0.105//register/
This error basically related to the path(#Path) in some cases. so please check your request path just like #Path("/event").
According to the response code, the client was able to communicate with a given server, but the server could not find what was requested.
So, in this case, should check path and parameter what are we sending.
If you are using #POST and want to send data using #part you need to first convert it to RequestBody before sending it. Do the following changes
In request code
Call<ResponsePojo> submitData(#Part MultipartBody.Part video,
#Part("device_id") RequestBody device_id,...
Before calling this method you need to convert your parameter to Requestbody
RequestBody device_id = RequestBody.create(
MediaType.parse("text/plain"),
device_id);
Now use this variable as mentioned above in method call.

Retrofit parse Json with array of parameter

I have a problem when parsing json by using Retrofit can't get any of data , This URL request array of parameter
https://lao.busnavi.asia/api/location.php?ids%5B%5D=132&ids%5B%5D=133&ids%5B%5D=131
JSON from server that looks like this
json data
My code
LatestBusLocation.java
#SerializedName("id") private int id;
#SerializedName("status") private int status;
#SerializedName("route_id") private String routeId;
#SerializedName("lng") private double lng;
#SerializedName("lat") private double lat;
#SerializedName("accuracy") private double accuracy;
#SerializedName("speed") private double speed;
#SerializedName("heading") private float heading;
#SerializedName("date") private Date date;
Interface class
public interface ApiService {
#POST("location.php")
Call<LatestBusLocation> loadLatestBusLocation(#Query("ids[]") int[] ids);
}
MainActivity.java
int[] ids = {131, 132, 133};
Call<LatestBusLocation> call = HttpManager.getInstance()
.getService().loadLatestBusLocation(ids);
call.enqueue(new Callback<LatestBusLocation>() {
#Override
public void onResponse(Call<LatestBusLocation> call, Response<LatestBusLocation> response) {
Log.e("WorkOrNote1", "Working");
if (response.isSuccessful()) {
dao = response.body();
Log.d("daoResponse", String.valueOf(dao.getId()));
} else {
try {
Log.e("LatestBusLocation", response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<LatestBusLocation> call, Throwable t) {
Log.e("onFailure", t.toString());
}
});
Retrofit fails to map your object because you have specified an LatestBusLocation in the Call. This should be a List<LatestBusLocation>.
Aditionally, you will have to add a deserializer to map correctlly because you are getting an object (with ids keys) instead of a proper array. Look at this relationed answer

Android Java Spring JSON response has $ in key. How to parse?

I'm new to Java. I'm using Spring to consume a REST api that outputs JSON. With the tutorials on the Spring website I can easily have the JSON response converted to an object of my desired class. The problem is now that one of the keys in the JSON response is $id. I cannot make a variable with a dollar sign in it. I assume I should define some configuration somewhere that such a name would be converted into something acceptable. I don't know how.
My Rest request code:
protected LoginResult doInBackground(Void... params) {
try {
Log.i(TAG, "Making Login request");
//TODO: Make this a setting
final String url = "https://someurl.com/api/login";
LoginCredentials login = new LoginCredentials("foo#bar.com", "qwerty123");
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
LoginResult result = restTemplate.postForObject(url, login, LoginResult.class);
Log.d(TAG, "Got the LoginResult.");
return result;
} catch (Exception e) {
//TODO: Exception handling
Log.e(TAG, e.getMessage(), e);
}
return null;
}
The resulting JSON looks something like this:
{
"_id":{
"$id":"98765432"
},
"name":"Person Guy",
"email":"foo#bar.com",
"roles":[
"user"
],
"active":true,
"created":{
"sec":1439117849,
"usec":856000
},
"session":{
"token":"12345678",
"user_id":"98765432",
"created":{
"sec":1439134272,
"usec":0
},
"last_extended":{
"sec":1439134272,
"usec":0
},
"expires":{
"sec":1439998272,
"usec":0
}
}
}
The $id part is where things get difficult. The LoginResult class looks like this:
#JsonIgnoreProperties(ignoreUnknown = true)
public class LoginResult {
private String name;
private String email;
private MongoId _id;
/* Getters and setters */
}
The MongoId class looks like this (The JsonIgnoreProperties is now added to avoid exceptions):
#JsonIgnoreProperties(ignoreUnknown = true)
public class MongoId {
private String id; //This is $id in the JSON response.
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Any help would be largely appreciated.
You can use the #JsonProperty("$id") annotation in MongoId to tell how the JSON is mapped to your Java object:
#JsonIgnoreProperties(ignoreUnknown = true)
public class MongoId {
#JsonProperty("$id")
private String id; //This is $id in the JSON response.
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
Here is a quick overview for reference.

Nested JSON Object (Retrofit)

I'm using Retrofit to send picture request and receive this Json
{"response":{
"face":{
"value":"true",
"confidence":55
},
"gender":{
"value":"male",
"confidence":73
},
...
}}
and I'm receiving it with Retrofit....
RestAdapter adapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(END_POINT)
.build();
Mylistenerr listener = adapter.create(Mylistenerr.class);
File photo = new File(picturePath);
TypedFile image = new TypedFile("multipart/image/jpg", photo);
listener.setUserImage(
image,
new Callback<respostring>() {
#Override
public void success(respostring rp, Response arg1) {}
#Override
public void failure(RetrofitError arg0) {
pd.hide();
pd.dismiss();
Log.d("ERROR:", arg0.getLocalizedMessage());
}
});
}
private static class respostring {
private Content face;
private Content gender;
respostring() {}
}
class Content
{
private int confidence;
private String value;
Content(){}
public int getconf(){
return this.confidence;
}
public String getvalue(){
return this.value;
}
}
My interface
public interface Mylistenerr {
#Multipart
#POST("/public/test")
void setUserImage(
#Part("image") TypedFile file,
Callback<respostring> response);
}
but there is retrofit error. Is there something I miss here?
I'd recommend you using Gson for json deserialization instead since retrofit supports it very well. Then you can just create classes like this:
Your face class:
public class Face implements Serializable {
#SerializedName("value")
public boolean value;
#SerializedName("confidence")
public int confidence;
}
Your gender class:
public class Gender implements Serializable {
#SerializedName("value")
public String value;
#SerializedName("confidence")
public int confidence;
}
your response class:
public class YourResponseType implements Serializable {
#SerializedName("face")
public Face face;
#SerializedName("gender")
public Gender gender;
}
Then you can actually make retrofit doing the rest for you:
listener.setUserImage(image, new Callback<YourResonseType>() {...});
Hope that helps!

Categories