how to Passing headers and body at a time in retrofit - android

Im sending 2 headers and a body of class type here
#POST("/api/access/change-password")
Call<JsonElement> changePassword(#Header("Content-Type") String content_type,
#Header("Authorization") String AuthToken,
#Body PostChangePassword postChangePassword);
here i am posting the data to server. but it returns some error. It is working fine in postman. but not in here.
public void postData(String old_password, String new_password) {
Log.v("im here in retro0", "");
PostChangePassword postChangePassword = new PostChangePassword(sharedPrefUserData.getUserData().getUserId(), sharedPrefUserData.getUserData().getAuthToken(), old_password, new_password);
mAPIService.changePassword("application/json", "Bearer " + sharedPrefUserData.getUserData().getAuthToken(), postChangePassword).enqueue(new Callback<JsonElement>() {
#Override
public void onResponse(Call<JsonElement> call, Response<JsonElement> response) {
Log.v("im here in retro1", response + "");
Gson gson = new Gson();
if (response.code() == 200) {
JsonElement jsonElement = response.body();
if (jsonElement.isJsonObject()) {
JsonObject objectWhichYouNeed = jsonElement.getAsJsonObject();
ResponseChangePassword object = gson.fromJson(objectWhichYouNeed, ResponseChangePassword.class);
}
} else {
Log.v("im here in retro2", response + "");
ResponseChangePassword responseChangePassword = null;
try {
responseChangePassword = gson.fromJson(response.errorBody().string(), ResponseChangePassword.class);
Toast.makeText(ProfileActivity.this, responseChangePassword.getMessage(), Toast.LENGTH_LONG).show();
} catch (IOException e) {
e.printStackTrace();
}
}
// progressBar.setVisibility(View.GONE);
}
#Override
public void onFailure(Call<JsonElement> call, Throwable t) {
// progressBar.setVisibility(View.GONE);
internetConnectionChecker.serverErrorAlert();
Log.v("im here in retro3", "");
}
});
}

Related

Problem in getting values from Json response

I am hitting a URL with four parameters, If parameters not match I will get the Following response.
This is my JSON response:
{
"result": "0"
}
Now my question is. How do I get that result value from response?
Here's, my Retrofit instance
public class RetrofitClientInstance {
private static Retrofit retrofit;
private static final String BASE_URL = "https://URL/";
public static Retrofit getRetrofitInstance() {
if (retrofit == null) {
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
Retrofit Interface
public interface ApiInterface {
#GET("f/f/ff.php")
Call<Object> verifyUser (#QueryMap Map< String, String > params );
}
Code for getting the response
ApiInterface apiInterface = RetrofitClientInstance.getRetrofitInstance().create(ApiInterface.class);
Call<Object> call = apiInterface.verifyUser(params);
call.enqueue(new Callback<Object>() {
#Override
public void onResponse(Call<Object> call, Response<Object> response) {
Log.e("Code ", response.code() + "");
if (!response.isSuccessful()) {
Log.e("Code ", response.code() + "");
return;
}
// Convert String to json object
JSONObject json = null;
String str_value = null;
try {
json = new JSONObject(String.valueOf(response));
//JSONObject json_LL = json.getJSONObject("result");
// get value from LL Json Object
str_value = json.getString("result"); //<< get value here
} catch (JSONException e) {
e.printStackTrace();
}
// Log.e("Response ", json.length() + "");
Toast.makeText(RegistrationForm.this, str_value, Toast.LENGTH_SHORT).show();
Object responseBody = response.body();
}
#Override
public void onFailure(Call<Object> call, Throwable t) {
Log.e("Failed", t.getMessage() + "");
}
});
Since you're using Gson. You can replace Object with a class that holds the fields that you want to parse.
for example:
public class ResultResponse {
String result;
public String getResult() {
return result;
}
public void setResult(String result) {
this.result = result;
}
}
And change your endpoint method to return this class.
public interface ApiInterface {
#GET("f/f/ff.php")
Call< ResultResponse> verifyUser (#QueryMap Map< String, String > params );
}
Also don't forget to change the remaining code to use the new return type ResultResponse
Call<ResultResponse> call = apiInterface.verifyUser(params);
call.enqueue(new Callback<ResultResponse>() {
#Override
public void onResponse(Call<ResultResponse> call, Response<ResultResponse> response) {
Log.e("Code ", response.code() + "");
if (!response.isSuccessful()) {
Log.e("Code ", response.code() + "");
return;
}
ResultResponse resultResponse = response.body();
String str_value = resultResponse.getResult();
Toast.makeText(RegistrationForm.this, str_value, Toast.LENGTH_SHORT).show();
}
#Override
public void onFailure(Call<Object> call, Throwable t) {
Log.e("Failed", t.getMessage() + "");
}
});

in arraylist data.size() showing 0 which i want to return

please help me how to return data added which i'm using to set data to
cardview in recyclerview.
i didn't understand why arraylist size returning zero.anyone please explain.
private List<NotificationData> prepareData() {
data = new ArrayList<>();
data.clear();
SharedPreferences prfs = getSharedPreferences("userdetails", Context.MODE_PRIVATE);
String outletid = prfs.getString("outletid", "");
String authkey = prfs.getString("authkey", "");
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://xxxxxx-yyyyy.zzzz.com/api/v1/outlet/cpf-ghh/" + outletid + "/")
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
FuelwareInterface fuelwareInterface = retrofit.create(FuelwareInterface.class);
Call<ResponseBody> responce_outlets;
Log.d("authkeyssss", "onClick: "+authkey);
responce_outlets = fuelwareInterface.getallindents(authkey);
responce_outlets.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
String result = response.body().string();
Log.d("like", "*** " + result);
JSONObject jsonObject = new JSONObject(result);
JSONArray jsonObject1=jsonObject.getJSONArray("data");
Log.d("ghllwnmm", "________"+jsonObject1.length());
int i=jsonObject1.length();
data.clear();
for (int j=0;j<i;j++){
JSONObject jsonObject2=jsonObject1.getJSONObject(j);
NotificationData notificationData = new NotificationData(jsonObject2.getString("vehicle_number"),
jsonObject2.getString("indent_number"),jsonObject2.getString("id"),
jsonObject2.getString("fill_type"),jsonObject2.getString("product"),
jsonObject2.getString("fill_date"),jsonObject2.getString("status"),
jsonObject2.getString("litre"),jsonObject2.getString("amount"));
data.add(notificationData);
}
Log.d("lk000jhgfs", "prepareMovieData: "+data.size());
adapter.notifyDataSetChanged();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}else {
Toast.makeText(getApplicationContext(),"Something Went Wrong",Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d("failuremethods", "content " + call.toString());
}
});
Log.d("lkjhgfs", "prepareMovieData: "+data.size());
return data;
}
data which i want to return showing size zero which i don't want.
The problem is return statement won't wait till onResponse method is called , so it will return 0 immediately, if you want to get the data, pass an interface to method and use callback to post as in
interface
public interface ResultCallback{
void onResult(List<NotificationData> data);
}
Method
private void prepareData(ResultCallback callback) { //< make it void
// some code
responce_outlets.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
String result = response.body().string();
Log.d("like", "*** " + result);
JSONObject jsonObject = new JSONObject(result);
JSONArray jsonObject1=jsonObject.getJSONArray("data");
Log.d("ghllwnmm", "________"+jsonObject1.length());
int i=jsonObject1.length();
data.clear();
for (int j=0;j<i;j++){
JSONObject jsonObject2=jsonObject1.getJSONObject(j);
NotificationData notificationData = new NotificationData(jsonObject2.getString("vehicle_number"),
jsonObject2.getString("indent_number"),jsonObject2.getString("id"),
jsonObject2.getString("fill_type"),jsonObject2.getString("product"),
jsonObject2.getString("fill_date"),jsonObject2.getString("status"),
jsonObject2.getString("litre"),jsonObject2.getString("amount"));
data.add(notificationData);
}
callback.onResult(data); //<this will push data back to caller
Log.d("lk000jhgfs", "prepareMovieData: "+data.size());
adapter.notifyDataSetChanged();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}else {
Toast.makeText(getApplicationContext(),"Something Went Wrong",Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Log.d("failuremethods", "content " + call.toString());
}
});
//some code
}
Calling method to get data
prepareData(new ResultCallback(){
#Override
public void onResult(List<NotificationData> data){
// log data.size you will get everything
}
});

Handle Multiple request in Android volley

I am trying to hit multiple request using Volley and i am getting response for all the request. my problem is how to identify the response is belong to which API.
mQueue = CustomVolleyRequest.getInstance(this.getApplicationContext())
.getRequestQueue();
final CustomJSONObjectrequest jsonRequest = new CustomJSONObjectrequest(Request.Method
.GET, url,
new JSONObject(), this, this); //
jsonRequest.setTag(REQUEST_TAG);
final CustomJSONObjectrequest jsonRequest2 = new CustomJSONObjectrequest(Request.Method
.GET, url2,
new JSONObject(), this, this);
jsonRequest2.setTag(REQUEST_TAG);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mQueue.add(jsonRequest);
mQueue.add(jsonRequest2); // Both the request will have different API request
}
});
}
#Override
public void onErrorResponse(VolleyError error) {
mTextView.setText(error.getMessage());
}
#Override
public void onResponse(Object response) {
// How to identify, which response is belong to which api request
mTextView.setText("Response is: " + response);
}
Create a Generic Volley class and a Interface, Use the interface to get success and failure responds.
Step 1 Create a separate Volley class
Step 2 Create a interface for accessing the response from volley class
Step 3 create new object for
the class and send required parameters
new PostVolleyJsonRequest(TestVolley.this, TestVolley.this(interfcae), "Submit", url, params);
Context of the class
Interface for sending Success and failure responds
Type of request to identify on success
url (mandatory)
Param (optional) for GET no need
Generic volley class
public class PostVolleyJsonRequest {
private String type;
private Activity act;
private VolleyJsonRespondsListener volleyJsonRespondsListener;
private String networkurl;
private JSONObject jsonObject = null;
private JSONObject params;
public PostVolleyJsonRequest(Activity act, VolleyJsonRespondsListener volleyJsonRespondsListener, String type, String netnetworkUrl,JSONObject params) {
this.act = act;
this.volleyJsonRespondsListener = volleyJsonRespondsListener;
this.type = type;
this.networkurl = netnetworkUrl;
this.params = params;
sendRequest();
}
private void sendRequest() {
Log.d("url", "url" + networkurl);
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST,networkurl,params,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.e("response", "response " + response);
volleyJsonRespondsListener.onSuccessJson(response, type);
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
try {
NetworkResponse response = error.networkResponse;
Log.e("response", "response " + response);
if (response != null) {
int code = response.statusCode;
String errorMsg = new String(response.data);
Log.e("response", "response" + errorMsg);
try {
jsonObject = new JSONObject(errorMsg);
} catch (JSONException e) {
e.printStackTrace();
}
String msg = jsonObject.optString("message");
volleyJsonRespondsListener.onFailureJson(code, msg);
} else {
String errorMsg = error.getMessage();
volleyJsonRespondsListener.onFailureJson(0, errorMsg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
jsObjRequest.setRetryPolicy(new DefaultRetryPolicy(
600000,
DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
RequestQueue requestqueue = Volley.newRequestQueue(act);
requestqueue.add(jsObjRequest);
}
}
Use the interface to get responds message
public interface VolleyJsonRespondsListener {
public void onSuccessJson(JSONObject result, String type);
public void onFailureJson(int responseCode, String responseMessage);
}
In your class where you want to include multiple request
public class TestVolley extends AppCompatActivity implements VolleyJsonRespondsListener{
//Your class code goes here
//network request
try {
//parameters
//Context,Interface,Type(to indentify your responds),URL,parameter for your request
//request 1
new PostVolleyJsonRequest(TestVolley.this, TestVolley.this, "Submit", url, params);
//request 2
new PostVolleyJsonRequest(TestVolley.this, TestVolley.this, "AccessData", url_2, params_2);
} catch (Exception e) {
e.printStackTrace()
}
//Methods from Interface
#Override
public void onSuccessJson(JSONObject result, String type) {
//Based on the Type you send get the responds and parse it
switch (type) {
case "Submit":
try {
parseSubmit(result);
} catch (Exception e) {
e.printStackTrace();
}
break;
case "AccessData":
try {
parseAccessData(result);
} catch (Exception e) {
e.printStackTrace();
}
break;
}
You can do something like this for a single request. Same can be applied to the second request. This way you know which request is giving you the response.
final CustomJSONObjectrequest jsonRequest = new CustomJSONObjectrequest(Request.Method
.GET, url,
new JSONObject(), this, new Response.Listener<Object>() {
#Override
public void onResponse(Object response) {
// How to identify, which response is belong to which api request
mTextView.setText("Response is: " + response);
});
EDITED :
You can start with making an interface like :
public interface VolleyResponse {
void onResponse(JSONObject object, String tag);
void onError(VolleyError error, String tag);
}
Then you can make a custom handler for volley request like:
public class CustomJSONObjectRequest implements Response.Listener<JSONObject>, Response.ErrorListener {
private VolleyResponse volleyResponse;
private String tag;
private JsonObjectRequest jsonObjectRequest;
public CustomJSONObjectRequest(int method, String url, JSONObject jsonObject, String tag, VolleyResponse volleyResponse) {
this.volleyResponse = volleyResponse;
this.tag= tag;
jsonObjectRequest = new JsonObjectRequest(method, url, jsonObject, this, this);
}
#Override
public void onResponse(JSONObject response) {
volleyResponse.onResponse(response, tag);
}
#Override
public void onErrorResponse(VolleyError error) {
volleyResponse.onError(error, tag);
}
public JsonObjectRequest getJsonObjectRequest() {
return jsonObjectRequest;
}
}
And to call it in your class use it like:
CustomJSONObjectRequest request1 = new CustomJSONObjectRequest(Request.Method.GET, url,
new JSONObject(), "YOUR REQUEST TAG", this);
Make sure to let your class implement the VolleyResponse interface that will get you the response and your tag.
#Override
public void onResponse(JSONObject object, String tag) {
Log.i("Response :", object.toString() + " " + tag);
}
#Override
public void onError(VolleyError error, String tag) {
}
To add the request to the volley queue you can use:
mQueue.add(request1.getJsonObjectRequest());
PS : this code is not tested but it should work.

How to get JSON error response in Volley onErrorResponse

I have an API call with below details
URL: http://pankajservers.in/api/v1/AuthenticateUser with Input params
below
EmailAddress and Password
if I type wrong credentials, I get below JSON response with Status Code : 403
{"Status":false,"Message":"Invalid Credentials. 5 attempts left.","Data":null}
Below is the Error Response Code.
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error)
{
if (null != error.networkResponse)
{
Log.d(TAG + ": ", "Error Response code: " + error.networkResponse.statusCode);
}
}
});
Is there any way to get JSON response in this code block?
I tried this post: Volley handle onErrorResponse
But it seems it never execute parseNetworkError
To print the Error on that block you just need to obtain the Response bytes:
NetworkResponse networkResponse = error.networkResponse;
if (networkResponse != null && networkResponse.data != null) {
String jsonError = new String(networkResponse.data);
// Print Error!
}
You can create custom request like this:
public class BaseRequest extends Request {
private static final String TAG = BaseRequest.class.getSimpleName();
private final Gson gson = new Gson();
private final Response.Listener listener;
public BaseRequest(String url, Response.Listener responseListener, Response.ErrorListener listener) {
super(Request.Method.GET, url, listener);
Log.e(TAG, "Requesting url : " + url);
this.listener = responseListener;
}
public BaseRequest(int method, String url, Response.Listener responseListener, Response.ErrorListener listener) {
super(method, url, listener);
Log.e(TAG, "Requesting url : " + url);
this.listener = responseListener;
}
#Override
public Response parseNetworkResponse(NetworkResponse response) {
try {
String json = null;
json = new String(
response.data,
HttpHeaderParser.parseCharset(response.headers));
JSONObject result = new JSONObject(json);
if (!result.getBoolean("Status"))
return Response.success(
result.get("Data"),
HttpHeaderParser.parseCacheHeaders(response));
else
return Response.error(new VolleyError(result.getString("Message")));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
} catch (JSONException e) {
return Response.error(new ParseError(e));
}
}
#Override
protected VolleyError parseNetworkError(VolleyError volleyError) {
return volleyError;
}
#Override
protected void deliverResponse(Object response) {
listener.onResponse(response);
}
}
and make request:
BaseRequest baseRequest = new BaseRequest(Request.Method.POST, url, new Response.Listener() {
#Override
public void onResponse(Object response) {
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Error : " + error.getMessage());
}
}) {
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
//Your parameters
return params;
}
};
queue.add(baseRequest);
You can cast an error response to a Json Object
JSONObject jsonObject = new JSONObject();
JsonObjectRequest JO = new JsonObjectRequest(Request.Method.POST,"URL String Here",jsonObject, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//Your Logic
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
try {
JSONObject JO = new JSONObject(error.toString());
}catch (JSONException e){
e.printStackTrace();
}
}
});

Retrofit 2 - string error body is empty

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;
}

Categories

Resources