I am just trying to show user data after hitting the API using Retrofit. my api response is:
{
"password":"111222333",
"name":"test name",
"email":"testem#gmail.com",
"username":"test1",
"customer_id":"201060",
"phone":"0196789"
}
but unfortunately, I am getting
"Expected BEGIN_OBJECT but was STRING at line 1 column 1 path $"
error.
I am totally stuck to show my json response.
My User.java class:
public class User {
#SerializedName("name")
#Expose
private String name;
#SerializedName("email")
#Expose
private String email;
#SerializedName("username")
#Expose
private String username;
#SerializedName("customer_id")
#Expose
private String customerId;
#SerializedName("phone")
#Expose
private String phone;
#SerializedName("password")
#Expose
private String password;
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public String getUsername() {
return username;
}
public String getCustomerId() {
return customerId;
}
public String getPhone() {
return phone;
}
public String getPassword() {
return password;
}
}
My Login class:
Gson gson = new GsonBuilder().setLenient().create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://us-central1-gmx-notification.cloudfunctions.net/")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
all_api = retrofit.create(allApi.class);
private void getUserDetails(String userName,String passWord){
Call<User> call = all_api.getUserDetails(userName,passWord);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
if(!response.isSuccessful()){
Log.d(response.body());
}
else{
User user = response.body();
String content = "";
content+= "Name: "+user.getName()+"\n";
content+= "Email: "+user.getEmail()+"\n";
content+= "Customer ID: "+user.getCustomerId()+"\n";
content+= "Phone: "+user.getPhone()+"\n";
Log.d(content);
}
});
}
and my retrofit api class:
package com.material.components;
import java.util.List;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Query;
public interface allApi {
#GET("login")
Call <User> getUserDetails(
#Query("email") String email,
#Query("password") String password
);
}
When i hit you api https://us-central1-gmx-notification.cloudfunctions.net/login?email=qwery#gmail.com&password=12345678
I got this response
Error: could not handle the request
So as your error says you expected Object but got a string. So or an error on the backend side or the request is incorrect or you forgot to add something to the request(Header or something else...).
For sure problem not in your model just got not a model that you expect in the response. Add Interceptor in your OkHttpClient to see what you get to be sure.
You need add this dependency to gradle
implementation 'com.squareup.okhttp3:logging-interceptor:3.9.1'
And here is a code example your API that will printing all networking stuff in the log:
public class NetworkManager {
private static RESTAuthService restAuthService;
/*timeout values in seconds*/
private static final int CONNECTION_TIMEOUT = 10;
private static final int WRITE_TIMEOUT = 10;
private static final int READ_TIMEOUT = 10;
static RESTAuthService getRESTAuthService() {
if (restAuthService == null) {
synchronized (NetworkManager.class) {
if (restAuthService == null) {
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new RESTInterceptor())
.connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(NetworkConfig.BASE_AUTH_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
restAuthService = retrofit.create(RESTAuthService.class);
}
}
}
return restAuthService;
}
private static class RESTInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Buffer buffer = new Buffer();
if (request.body() != null) {
request.body().writeTo(buffer);
}
Log.d("HTTP Request", "Request to " + request.url().toString()
+ "\n" + request.headers().toString()
+ "\n" + buffer.readUtf8());
long t1 = System.nanoTime();
Response response = chain.proceed(request);
long t2 = System.nanoTime();
String msg = response.body().string();
msg = msg.replace("\r", ""); // Note: Messages with '\r' not displayed correctly in logcat
Log.d("HTTP Response", String.format("Response from %s in %.1fms%n\n%s",
response.request().url().toString(), (t2 - t1) / 1e6d, msg));
Log.d("HTTP Response", "Response code = " + response.code());
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), msg))
.build();
}
}
}
Your MyLogin class will be something like this:
public class MuLogin {
/*timeout values in seconds*/
private static final int CONNECTION_TIMEOUT = 10;
private static final int WRITE_TIMEOUT = 10;
private static final int READ_TIMEOUT = 10;
allApi = all_api;
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new RESTInterceptor())
.connectTimeout(CONNECTION_TIMEOUT, TimeUnit.SECONDS)
.writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS)
.readTimeout(READ_TIMEOUT, TimeUnit.SECONDS)
.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://us-central1-gmx-notification.cloudfunctions.net/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
all_api =retrofit.create(allApi.class);
public void getUserDetails(String userName, String passWord) {
Call<User> call = all_api.getUserDetails(userName, passWord);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
if (!response.isSuccessful()) {
Log.d(response.body());
} else {
User user = response.body();
String content = "";
content += "Name: " + user.getName() + "\n";
content += "Email: " + user.getEmail() + "\n";
content += "Customer ID: " + user.getCustomerId() + "\n";
content += "Phone: " + user.getPhone() + "\n";
Log.d(content);
}
});
}
}
private static class RESTInterceptor implements Interceptor {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Buffer buffer = new Buffer();
if (request.body() != null) {
request.body().writeTo(buffer);
}
Log.d("HTTP Request", "Request to " + request.url().toString()
+ "\n" + request.headers().toString()
+ "\n" + buffer.readUtf8());
long t1 = System.nanoTime();
Response response = chain.proceed(request);
long t2 = System.nanoTime();
String msg = response.body().string();
msg = msg.replace("\r", ""); // Note: Messages with '\r' not displayed correctly in logcat
Log.d("HTTP Response", String.format("Response from %s in %.1fms%n\n%s",
response.request().url().toString(), (t2 - t1) / 1e6d, msg));
Log.d("HTTP Response", "Response code = " + response.code());
return response.newBuilder()
.body(ResponseBody.create(response.body().contentType(), msg))
.build();
}
}
}
Related
I have a function inside a aar module that needs to wait the onResponse() or onError() response by using AndroidNetworking. The output is the return executes first before waiting on whatever response it will received. I'm having a problem on waiting the response to return on my app. I also used synchronized on the function. this is the code on my module
public static synchronized String getActivationData(final Context context, final String api, final String base64Header, final String endpoint, final JSONObject body) {
final String[] result = {null};
new Thread(new Runnable() {
#Override
public void run() {
StrictMode.ThreadPolicy policy =
new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
String baseURL = null;
if (api.equalsIgnoreCase("LOCAL")) {
baseURL = Environments.getMarkLocalAPI();
} else if (api.equalsIgnoreCase("DEVELOPMENT")) {
baseURL = Environments.getDevelopmentAPI();
} else if (api.equalsIgnoreCase("STAGING")) {
baseURL = Environments.getStagingAPI();
} else if (api.equalsIgnoreCase("DEPLOYMENT")) {
baseURL = Environments.getDeploymentAPI();
}
final String finalBaseURL = baseURL;
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build();
AndroidNetworking.initialize(context, okHttpClient);
AndroidNetworking.post(finalBaseURL + endpoint)
.setPriority(Priority.HIGH)
.addJSONObjectBody(body)
.addHeaders("Project", base64Header)
.addHeaders("Content-Type", "application/json")
.build()
.getAsJSONObject(new JSONObjectRequestListener() {
#Override
public void onResponse(JSONObject response) {
result[0] = String.valueOf(response);
}
#Override
public void onError(ANError anError) {
if (anError.getErrorCode() != 0) {
result[0] = String.valueOf(anError.getErrorDetail());
} else {
result[0] = String.valueOf(anError.getErrorDetail());
}
}
});
Log.i("data", result[0]);
}
}).start();
return result[0];
}
and calling the function on my App via :
String data = ActivationResponseV2.getActivationData(getContext(), "LOCAL", header, "/sample/response", jsonObject);
may I know what I'm doing wrong?. Thanks!
Response was returned outside the post call: To handle this you can pass a callback method to your function to consume the result when its ready.
public static void getActivationData(final Context context,
final String api, final String base64Header, final String endpoint,
final JSONObject body, Callable<Void> methodParam) {
String baseURL = null;
if (api.equalsIgnoreCase("LOCAL")) {
baseURL = Environments.getMarkLocalAPI();
} else if (api.equalsIgnoreCase("DEVELOPMENT")) {
baseURL = Environments.getDevelopmentAPI();
} else if (api.equalsIgnoreCase("STAGING")) {
baseURL = Environments.getStagingAPI();
} else if (api.equalsIgnoreCase("DEPLOYMENT")) {
baseURL = Environments.getDeploymentAPI();
}
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build();
AndroidNetworking.initialize(context, okHttpClient);
AndroidNetworking.post(baseURL + endpoint)
.setPriority(Priority.HIGH)
.addJSONObjectBody(body)
.addHeaders("Project", base64Header)
.addHeaders("Content-Type", "application/json")
.build()
.getAsJSONObject(new JSONObjectRequestListener() {
#Override
public void onResponse(JSONObject response) {
//result[0] = String.valueOf(response);
methodParam.call(String.valueOf(response));
}
#Override
public void onError(ANError anError) {
if (anError.getErrorCode() != 0) {
// result[0] = String.valueOf(anError.getErrorDetail());
} else {
//result[0] = String.valueOf(anError.getErrorDetail());
}
methodParam.call(String.valueOf(anError.getErrorDetail()));
}
});
// Log.i("data", result[0]);
}
Use like below
ActivationResponseV2.getActivationData(getContext(), "LOCAL", header,
"/sample/response", jsonObject, new Callable<Void>() {
public Void call(String data) {
//...Consume data here
return null;
});
I have done it by using ANRequest. After reading this document. I tried to replicate it and I get my desired output.
This is the code :
public static synchronized String getActivationData(final Context context, final String api, final String base64Header, final String endpoint, final JSONObject body) {
final String[] result = {null};
String baseURL = null;
if (api.equalsIgnoreCase("LOCAL")) {
baseURL = Environments.getMarkLocalAPI();
} else if (api.equalsIgnoreCase("DEVELOPMENT")) {
baseURL = Environments.getDevelopmentAPI();
} else if (api.equalsIgnoreCase("STAGING")) {
baseURL = Environments.getStagingAPI();
} else if (api.equalsIgnoreCase("DEPLOYMENT")) {
baseURL = Environments.getDeploymentAPI();
}
final String finalBaseURL = baseURL;
OkHttpClient okHttpClient = new OkHttpClient().newBuilder()
.connectTimeout(15, TimeUnit.SECONDS)
.readTimeout(15, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build();
AndroidNetworking.initialize(context, okHttpClient);
ANRequest request = AndroidNetworking.post(finalBaseURL + endpoint)
.setPriority(Priority.HIGH)
.addJSONObjectBody(body)
.addHeaders("Project", base64Header)
.addHeaders("Content-Type", "application/json")
.build();
ANResponse response = request.executeForJSONObject();
if (response.isSuccess()) {
result[0] = String.valueOf(response.getResult());
Log.d(TAG, "response : " + result[0]);
} else {
ANError error = response.getError();
Log.d(TAG, "response : " + error);
}
return result[0];
}
}
Happy Coding!
I am hitting this API https://westus.dev.cognitive.microsoft.com/docs/services/563309b6778daf02acc0a508/operations/563309b7778daf06340c9652/console
below is my retrofit code. I am not able to send raw JSON in retrofit.
public void createProfileAPI()
{
ApiInterface apiService = ApiClient.getClientRequest().create(ApiInterface.class);
try
{
//pbVrd.setVisibility(View.VISIBLE);
JSONObject paramObject = new JSONObject();
paramObject.put("locale", "en-us");
LocaleModel localeModel = new LocaleModel();
localeModel.setLocale("en-us");
Call<BaseModel> call = apiService.SearchResponse(localeModel);
call.enqueue(new Callback<BaseModel>()
{
#Override
public void onResponse(Call<BaseModel> call, Response<BaseModel> response)
{
int responseCode = response.code();
Log.d("Deepakw" , responseCode+"");
BaseModel response1 = response.body();
Log.d("Deepak" , response.body().getIdentificationProfileId() + " //// " +response1.getIdentificationProfileId()+"");
}
#Override
public void onFailure(Call<BaseModel> call, Throwable t)
{
Log.d("Responce Failed ", "failed Response Mersen Fuse ");
String message = t.getMessage();
Log.d("failure", message);
}
});
}
catch (Exception e)
{
e.printStackTrace();
}
}
public class ApiClient {
public static final String BASE_URL = "https://westus.api.cognitive.microsoft.com/spid/v1.0/";
private static Retrofit retrofit = null;
public static Retrofit getClientRequest() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
public interface ApiInterface {
#Headers({
"Content-Type: application/json",
"Ocp-Apim-Subscription-Key: 0219cf3e3d444f0584f80b3a84613d12"
})
#POST("verificationProfiles")
Call<BaseModel> SearchResponse(#Body LocaleModel body);
};
I am not able to get response
API client
Please help
//In ApiInterface do like this
#Headers("charset:UTF-8")
#POST("verificationProfiles")
Call<BaseModel> SearchResponse(
#Header("Content-Type") String contentType,
#Body LocaleModel body);
have you tried #SerializedName("") and #Expose in your pojo class
#SerializedName("status")
#Expose
private Boolean status;
Instead of JSONObject, you can use Map
For example:
Headers("Content-Type: application/json")
#POST("/apipath")
request(#Body Map<String, String> body);
I am trying to implement sendOTP of MSG91.There I have to API ,one for generating otp and another one for verifying otp.But there in post reuest I have to set a header ,so how can I set header in retrofit.I am attaching a pic of what to do.Please help me.enter image description here
post request:-
public class GenerateOTPRequest {
String countryCode;
String mobileNumber;
public GenerateOTPRequest(String countryCode, String mobileNumber) {
this.countryCode = countryCode;
this.mobileNumber = mobileNumber;
}
public String getCountryCode() {
return countryCode;
}
public void setCountryCode(String countryCode) {
this.countryCode = countryCode;
}
public String getMobileNumber() {
return mobileNumber;
}
public void setMobileNumber(String mobileNumber) {
this.mobileNumber = mobileNumber;
}
}
Response:-
public class GenerateOTPResponse {
#SerializedName("status")
#Expose
String status;
#SerializedName("response")
#Expose
String response;
public GenerateOTPResponse(String status, String response) {
this.status = status;
this.response = response;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
}
my main activity:-
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_verify_otp);
CalligraphyConfig.initDefault(new CalligraphyConfig.Builder()
.setDefaultFontPath("fonts/opensanslight.ttf")
.setFontAttrId(R.attr.fontPath)
.build()
);
getSupportActionBar().setTitle("Verify Your OTP");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
enterOTP = (EditText) findViewById(R.id.enter_otp);
verifyOTP = (Button) findViewById(R.id.verify_otp);
didntReceiveOTP = (TextView) findViewById(R.id.verify_otp_didnt_receive_otp);
sharedpreferences = getSharedPreferences(MyPREFERENCES, Context.MODE_PRIVATE);
phone = sharedpreferences.getString(Phone, "notPresent");
Log.d("jkhdds: ", "" + phone);
GenerateOTPRequest generateOTPRequest = new GenerateOTPRequest("","");
generateOTPRequest.setCountryCode("91");
generateOTPRequest.setMobileNumber(phone);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("application-key", "oEBg-3z4hgcv5X8sk_AYdVDiqpGCN02G3cFRjCK0er6MWhuSHAQDRT3TuJKxzOI__2H3D_gZZWeMJsns92zEm4LlksdilXYePbiFZRc1OLZxZd1DmSQOlmM-MIhDrXOqefgIVJX_deqP0QfRoBZ-PtlqpCtZFRqem1kl_J2Vra8=")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
OkHttpClient client = httpClient.build();
Retrofit retrofit1 = new Retrofit.Builder()
.baseUrl("https://sendotp.msg91.com/api/")
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.build();
final API service1 = retrofit1.create(API.class);
Call<GenerateOTPResponse> call = service1.generateOTP(generateOTPRequest);
call.enqueue(new Callback<GenerateOTPResponse>() {
#Override
public void onResponse(Call<GenerateOTPResponse> call, retrofit2.Response<GenerateOTPResponse> response) {
//GenerateOTPResponse generateOTPResponse = response.body();
//String status = otpResponse.getStatus();
Log.d("otp response " , response.body().getResponse());
}
#Override
public void onFailure(Call<GenerateOTPResponse> call, Throwable t) {
}
});
Log.d("Tag", String.valueOf(enterOTP.getText()));
OkHttpClient.Builder httpClient1 = new OkHttpClient.Builder();
httpClient.addInterceptor(new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain) throws IOException {
Request original = chain.request();
Request request = original.newBuilder()
.header("application-key", "oEBg-3z4hgcv5X8sk_AYdVDiqpGCN02G3cFRjCK0er6MWhuSHAQDRT3TuJKxzOI__2H3D_gZZWeMJsns92zEm4LlksdilXYePbiFZRc1OLZxZd1DmSQOlmM-MIhDrXOqefgIVJX_deqP0QfRoBZ-PtlqpCtZFRqem1kl_J2Vra8=")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
}
});
OkHttpClient client1 = httpClient1.build();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://sendotp.msg91.com/api/")
.addConverterFactory(GsonConverterFactory.create())
.client(client1)
.build();
final API service = retrofit.create(API.class);
Log.d("Tag",enterOTP.getText().toString());
Log.d("Tag","fuck u");
verifyOTP.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final VerifyOTPRequest verifyOTPRequest = new VerifyOTPRequest("","","");
verifyOTPRequest.setCountryCode("91");
verifyOTPRequest.setMobileNumber(phone);
verifyOTPRequest.setOneTimePassword(enterOTP.getText().toString());
Log.d("Tag",enterOTP.getText().toString());
Call<VerifyOTPResponse> call = service.verifyOTP(verifyOTPRequest);
call.enqueue(new Callback<VerifyOTPResponse>() {
#Override
public void onResponse(Call<VerifyOTPResponse> call, retrofit2.Response<VerifyOTPResponse> response) {
Log.d("Tag", String.valueOf(response.body()));
String message = response.body().getStatus();
Log.d("Tag",message);
if (message.equals("success")) {
Toast.makeText(getApplicationContext(), "Successfully Verified", Toast.LENGTH_LONG).show();
Intent intent1 = getIntent();
String parentActivityName = intent1.getStringExtra("activity");
if (parentActivityName.equals("signup")) {
Intent selectSubject = new Intent(VerifyOTPActivity.this, SelectSubjectActivity.class);
progressDialog.dismiss();
startActivity(selectSubject);
} else {
Intent changepassword = new Intent(VerifyOTPActivity.this, ChangePasswordActivity.class);
progressDialog.dismiss();
startActivity(changepassword);
}
}
Log.d("message csdkhds", "" + message);
Log.d("phonre : ", " " + phone);
}
#Override
public void onFailure(Call<VerifyOTPResponse> call, Throwable t) {
}
});
}
});
}
my interface:-
#POST("generateOTP")
Call<GenerateOTPResponse> generateOTP(#Body GenerateOTPRequest generateOTPRequest);
#POST("verifyOTP")
Call<VerifyOTPResponse> verifyOTP(#Body VerifyOTPRequest verifyOTPRequest);
Just use annotation:
public interface Service {
#Headers("application-Key", your key)
#GET("/example")
Call<List<Example>> getExamples();
}
All examples are available here: https://futurestud.io/tutorials/retrofit-add-custom-request-header
You can use #Header annotation for your api method as it is clearly stated in a documentation https://square.github.io/retrofit/
#Headers("XYZ: value")
you can set it in your base retrofit file
request = original.newBuilder()
.header("header key", "your header)
.header("x-requested-with", "XMLHttpRequest")
.method(original.method(), original.body())
.build();
okhttp3.Response response = chain.proceed(request);
#Header
this is a Retrofit specific annotation which will allow you the pass the request headers to the targeting HTTP endpoint, where every argument represents a request header entry.
Server returns JSON object in case of success and simple String for error case.
There are no problems with parsing JSON into object. The problem rises when I want to parse error since the response.errorBody().string() is empty.
When I send the same request using Postman the response as follows:
And I can't read this error... Anyone faced such problem?
Code code
gradle:
compile 'com.squareup.retrofit2:retrofit:2.0.0-beta4'
compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'
compile 'com.squareup.okhttp:okhttp:2.6.0'
RestClient.java:
private static GitApiInterface gitApiInterface;
...
public static GitApiInterface getClient() {
if (gitApiInterface == null) {
OkHttpClient okClient = new OkHttpClient();
okClient.interceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response;
}
});
Retrofit client = new Retrofit.Builder()
.baseUrl(URL_BASE)
.addConverterFactory(GsonConverterFactory.create())
.build();
gitApiInterface = client.create(GitApiInterface.class);
}
return gitApiInterface;
}
ApiInterface.java:
public interface ApiInterface {
#POST("/register/user/{email}/")
Call<User> postRegisterUser(#Path(value = "email", encoded = true) String email,
#Query("firstname") String firstName,
#Query("lastname") String lastName,
#Query("country") String country,
#Query("phone") String phone,
#Query("deviceid") String deviceId);
...
ServerRequests.java:
public void registerUser(#NonNull String email,
#NonNull String firstName,
#NonNull String lastName,
#NonNull String country,
#NonNull String phone,
#NonNull String deviceId,
#NonNull final RegisterUserCallback callback) {
showProgressBar();
RestClient.GitApiInterface service = RestClient.getClient();
Call<User> call = service.postRegisterUser(email, firstName, lastName, country, phone, deviceId);
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
hideProgressBar();
User user = response.body(); //this works great
if (response.isSuccess()) {
Log.d(TAG, "REGISTER success: " + response.message());
callback.onRegisteredUser(user);
} else {
try {
Log.e(TAG, "REGISTER fail: " + response.errorBody().string()); //empty error body
callback.onRegisterFailed(response.errorBody().string());
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<User> call, Throwable t) {
hideProgressBar();
callback.onRegisterFailed("error");
}
});
}
My answer is based on HttpLoggingInterceptor class.
I wrote getStatusError() method by given in parameter response.errorBody().
private StatusError getStatusError(ResponseBody responseBody) {
StatusError statusError = null;
if (responseBody != null) {
try {
BufferedSource source = responseBody.source();
if (source != null) {
source.request(Long.MAX_VALUE); // Buffer the entire body.
Buffer buffer = source.buffer();
Charset charset = UTF8;
MediaType contentType = responseBody.contentType();
if (contentType != null) {
charset = contentType.charset(UTF8);
}
String string = buffer.clone().readString(charset);
if (!TextUtils.isEmpty(string)) {
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
statusError = gson.fromJson(string, StatusError.class);
}
}
} catch (Exception e) {
LogUtils.LOGW(TAG, "Impossible to get StatusError stream", e);
}
}
return statusError;
}
StatusError is a POJO class to map (JSON) elements:
public class StatusError {
#SerializedName("message")
public String message;
#SerializedName("errors")
public ArrayList<ErrorDetail> errors;
}
I use Retrofit 2 library, and I need to send POST JSON request like this:
{
"datetime": 0,
"body": {
"gymId": "17C1B14C-C21F-41EE-BF75-F0E7843DB638",
"customerName": "test",
"customerEmail": "test#test.ru",
"content": "test"
}
}
How i can send this request use RequestBody?
Call<ApiClubRequest> clubContact(#Body RequestBody requestBody);
Or can easily make such a request?
This is my interface class with OkHttp settings.
public class RestClient {
private static ClassApiInterface WordClassApiInterface ;
private static String baseUrl = "http://my adddress" ;
public static WorldClassApiInterface getClient() {
if (WordClassApiInterface == null) {
OkHttpClient okClient = new OkHttpClient();
okClient.interceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Response response = chain.proceed(chain.request());
return response;
}
});
Retrofit client = new Retrofit.Builder()
.baseUrl(baseUrl)
.client(okClient)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface = client.create(ApiInterface.class);
}
return ClassApiInterface ;
}
public static Call<ApiClubRequest> clubcontact(String gymId, String customerName, String
customerEmail, String content){
ClubContactRequest request = new ClubContactRequest();
request.gymId = gymId;
request.customerName = customerName;
request.customerEmail = customerEmail;
request.content = content;
return ApiInterface.clubContact(request);
}
#Headers("Content-Type: application/json")
#POST("/hotline")
Call<ApiClubRequest> clubContact(#Body ClubContactRequest requestBody);
}
}
Create a request class and create fields with the same name as in the JSON:
public class ClubContactRequest {
public String gymId;
public String customerName;
public String customerEmail;
public String content;
}
Modify the POST #Body:
Call<ApiClubRequest> clubContact(#Body ClubContactRequest requestBody);
Then implement the request:
public Call<ApiClubRequest> clubcontact(String gymId, String customerName, String customerEmail, String content){
ClubContactRequest request = new ClubContactRequest();
request.gymId = gymId;
request.customerName = customerName;
request.customerEmail = customerEmail;
request.content = content;
return yourApiInterface.clubContact(request);
}