custom error Response for volley - android

I have a Stringrequest in Android Studio and it's working correctly, I mean I get the response on onResponse method, now I want volley to return an error when the error key has true value. how can i do it?
this is my request:
StringRequest stringRequest = new StringRequest(Request.Method.POST, METHOD_ACCOUNT_OTP_REQUEST,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.i("response", response);
try {
JSONObject jsonObject = new JSONObject(response);
startVerificationActivity(jsonObject.get("sender").toString());
} catch (JSONException e) {
e.printStackTrace();
Log.i("error", e.toString());
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
}
}){
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("mobilePhoneNumber", phoneNumber);
params.put("clientId", CLIENT_ID);
return params;
};
this is the answer of the server:
{"sender":"10008727","error":true}
all I want is to set volley to run onErrorResponse when error is true in the json.

You can create a new custom AppStringRequest class which inherits from StringRequest and handle the above usecase.
public class AppStringRequest extends StringRequest {
// ... constructor ...
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
// You will receive your response here in the response parameter.
// parse the response and check whether the response has "error":true
String parsed;
try {
parsed = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
} catch (UnsupportedEncodingException e) {
parsed = new String(response.data);
}
// if it's an error, return Response.error(), otherwise, return Response.success()
try {
JSONObject resObj = new JSONObject(parsed);
boolean error = resObj.getBoolean("error");
if (error) {
return Response.error(new VolleyError());
} else {
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
}
} catch (JSONException e) {
e.printStractTrace()
// your server response has some issues
}
return Response.error(new VolleyError("Error message")); // can send error message in the VolleyError
}
}
Then you have to use this AppStringRequest instead of the default StringRequest.
StringRequest stringRequest = new AppStringRequest(Request.Method.POST, METHOD_ACCOUNT_OTP_REQUEST,
... )
The error message will be available in the onErrorResponse:
#Override
public void onErrorResponse(VolleyError error) {
Log.i("Volley error", error.toString()); //the error message
}

Related

VOLLEY ERROR : Unexpected response code 400

I am trying to send JSON using POST. But I am getting the following error.
Volley: NetworkUtility.shouldRetryException: Unexpected response code 400 for "URL"
I don't understand the issue. If I'm doing anything wrong in the below code, please let me know. Thank you.
private void postDataUsingVolley(String dev_id, String payload_raw) {
try {
RequestQueue requestQueue = Volley.newRequestQueue(this);
JSONObject params = new JSONObject();
params.put("dev_id", dev_id);
params.put("port", "1");
params.put("confirmed", "false");
params.put("payload_raw", payload_raw);
params.put("schedule", "replace");
final String mRequestBody = params.toString();
StringRequest stringRequest = new StringRequest(Request.Method.POST, DOWNLINK_URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.i("LOG_VOLLEY", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("LOG_VOLLEY", error.toString());
}
}) {
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
return mRequestBody == null ? null : mRequestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", mRequestBody, "utf-8");
return null;
}
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String responseString = "";
if (response != null) {
responseString = String.valueOf(response.statusCode);
}
return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
}
};
requestQueue.add(stringRequest);
} catch (JSONException e) {
e.printStackTrace();
}
}
Instead of StringRequest make a JsonObjectRequest directly, put your data in a JSON object and send the request to the network.
Like this:-
private void postDataUsingVolley(String dev_id, String payload_raw) {
JSONObject params = new JSONObject();
try {
params.put("dev_id", dev_id);
params.put("port", "1");
params.put("confirmed", "false");
params.put("payload_raw", payload_raw);
params.put("schedule", "replace");
}
catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest request=new JsonObjectRequest(Request.Method.POST, DOWNLINK_URL, params, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("Response", ""+response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error", error.getMessage());
}
}) ;
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(request);
}

How to fix JSONException Error in Volley library?

I am trying to send a JSON object request with two parameters and in response trying to get an array from the api call. However, I am getting exception parse error in Error listener. A post request is sent when the button is clicked. The func takes two parameters but fails to get response, the function directly goes to on response error listener
private void validate_log(String num) {
/*buttonNumCheck.setVisibility(View.INVISIBLE);
final ProgressBar pBar=(ProgressBar)findViewById(R.id.progressBarLogin);
pBar.setVisibility(View.VISIBLE);*/
buttonNumCheck.setInProgress(true);
buttonNumCheck.setEnabled(false);
final String Org_id="81";
final String url="http://xya/api";
RequestQueue rq=Volley.newRequestQueue(this);
JSONObject js=new JSONObject();
try {
js.put("parm1", num);
js.put("parm2", Org_id);
final String requestBody=js.toString();
} catch (JSONException e) {
e.printStackTrace();
}
JsonObjectRequest jsonObjReq=new JsonObjectRequest(
Request.Method.POST, url, js,
new Response.Listener<JSONObject>() {
public void onResponse(JSONObject response) {
buttonNumCheck.setEnabled(true);
buttonNumCheck.setInProgress(false);
String stresponse=response.toString();
Toast.makeText(getApplicationContext(),"REPOSE="+response,Toast.LENGTH_SHORT).show();
System.out.println("RESPONSE= "+response);
try {
JSONArray heroArray = response.getJSONArray("");
// Toast.makeText(DeviceCheck_Activity.this, "Welcome Back"+ [1], Toast.LENGTH_LONG).show();
} catch (JSONException e) {
e.printStackTrace();
Log.e("Error", "Response Error", e);
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(DeviceCheck_Activity.this, "Response error= " + error, Toast.LENGTH_LONG).show();
/*mdToast=MDToast.makeText(getApplicationContext(), "Oops something went wrong!!",
Toast.LENGTH_SHORT, MDToast.TYPE_ERROR);
mdToast.show();*/
buttonNumCheck.setInProgress(false);
buttonNumCheck.setEnabled(true);
Log.e("Error", "Response Error", error);
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers=new HashMap<String, String>();
headers.put("Content-Type", "application/json; charset=utf-8");
return headers;
}
};
jsonObjReq.setShouldCache(false);
jsonObjReq.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
rq.add(jsonObjReq);
}
The error response I am getting is
com.android.volley.ParseError: org.json.JSONException: Value [{"store_id":11,"store_name":"Gomati District Main Store"},{"store_id":13,"store_name":"Main Seed Store"}] of type org.json.JSONArray cannot be converted to JSONObject
Your Problem can be solved in 2 ways :
First:)
Using JSONArrayRequest instead of JSONbjectRequest.
Your JSONObjectRequest returns an JSONObject response while your response is an JSONArray therefore java can not convert it and your application crashes.
Change you request as below:
JSONArrayRequest jsonArrReq=new JSONArrayRequest(//changed
Request.Method.POST, url, js,
new Response.Listener<JSONArray>() {
public void onResponse(JSONArray response) {
JSONArray heroArray = response;//changeed
/* rest of your code */
} catch (JSONException e) {
e.printStackTrace();
Log.e("Error", "Response Error", e);
}
}
},
jsonArrReq.setShouldCache(false);
jsonArrReq.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
rq.add(jsonArrReq);
Second :)
Using StringRequest instead of JSONObjectRequest. String request returns an String response which lets you do what ever you want with your response.
Change you request as below :
StringRequest stringRequest = new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
JSONArray heroArray = new JSONArray(response);
/* rest of your code */
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Error", "Response Error", error);
/*rest of your code */
}
}) {
#Override
public byte[] getBody() throws AuthFailureError {
try {
return requestBody == null ? null : js.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", js, "utf-8");
return null;
}
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String responseString = "";
if (response != null) {
responseString = String.valueOf(response.statusCode);
// can get more details such as response.headers
}
return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
}
};
}
stringRequest.setShouldCache(false);
stringRequest.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
rq.add(stringRequest);
Use the JsonArrayRequest like thisas your response is JsonArray .
JsonArrayRequest jsonObjReq = new JsonArrayRequest(Request.Method.POST, url, js,
new Response.Listener<JSONArray>() {
public void onResponse(JSONArray response) {
buttonNumCheck.setEnabled(true);
buttonNumCheck.setInProgress(false);
String stresponse = response.toString();
try {
for (int i = 0; i < response.length(); i++) {
JSONObject object = response.getJSONObject(i);
String id = object.getString("store_id");
}
} catch (JSONException e) {
e.printStackTrace();
Log.e("Error", "Response Error", e);
}
}
}
Tried all the solutions didn't worked but thank you guys for your help. I actually found the solution from another question posted in stack overflow page. Here is the solution:
RequestQueue requestQueue=Volley.newRequestQueue(getApplicationContext());
StringRequest stringRequest=new StringRequest(Request.Method.POST, url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
//JSONArray jsonArray_1=new JSONArray(response);
System.out.println("RESPONSE= " + response);
JSONArray jsonArray=new JSONArray(response);
json_stringarr=new String[jsonArray.length()];
if(jsonArray.length()>0) {
for (int i=0; i < jsonArray.length(); i++) {
JSONObject jsonObject1=jsonArray.getJSONObject(i);
//String web_page=jsonObject1.getString("awb_no");
String store_id=jsonObject1.getString("store_id");
String store_name=jsonObject1.getString("store_name");
json_stringarr[i]=store_id+" - "+store_name;
Toast.makeText(getApplicationContext(), "RESPOBBSE= " + json_stringarr[i], Toast.LENGTH_SHORT).show();
System.out.println("JSON ARRAY=" + json_stringarr[i]);
System.out.println("JSON Object=" + jsonObject1);
}
}
else{
Toast.makeText(getApplicationContext(),"Login ceredentils are incorrect",Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
MDToast mdToast=MDToast.makeText(getApplicationContext(), "Something went wrong!!", Toast.LENGTH_SHORT, MDToast.TYPE_WARNING);
mdToast.show();
error.printStackTrace();
}
}) {
#Override
public byte[] getBody() {
// String body="{\"param1\":"+num+",\"param2\":\"81"\"}";
String body="{\"parm1\":"+num+",\"parm2\":\"81\"}";
return body.getBytes();
}
/*#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("param1", num);
params.put("param2", Org_id);
return params;
}*/
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers=new HashMap<String, String>();
headers.put("Content-Type", "application/json; charset=utf-8");
return headers;
}
};
I did it by sending a String request and then overriding the getBody() method and then it worked like a charm. Thanks again for all your help.

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

Android Volley onResponse get data

In a string post request for logging in. in onResponse all i am returned is the status code of 200. I would like to get the data returned as well. I am not sure where to go from this point forward? Any ideas on how to get the data returned, and not just the status code?
public void requestWithSomeHttpHeaders() {
try {
RequestQueue requestQueue = Volley.newRequestQueue(this);
String URL = "http://......";
JSONObject jsonBody = new JSONObject();
jsonBody.put("username", "yourusername");
jsonBody.put("password", "yourpassword");
final String mRequestBody = jsonBody.toString();
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.i("VOLLEY", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY", error.toString());
}
}) {
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
return mRequestBody == null ? null : mRequestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", mRequestBody, "utf-8");
return null;
}
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String responseString = "";
if (response != null) {
responseString = String.valueOf(response.statusCode);
// can get more details such as response.headers
System.out.println(responseString);
}
return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
}
};
requestQueue.add(stringRequest);
} catch (JSONException e) {
e.printStackTrace();
}
}
Preferably, define a method.
private void doLogin() {
// TODO: startActivity?
}
Then call that
StringRequest stringRequest = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.i("VOLLEY", response);
doLogin();
}
If you want the data from the server, that is what String response is. Check your Logcat.
As mentioned in the comments, using StringRequest without implementing getBody, parseNetworkResponse, and getBodyContentType might work better.
If you want to parse JSON add method like this
public Profile getUserProfile(String response){
Profile profile = null;
try {
profile = new Profile();
JSONObject jsonObject = new JSONObject(response);
profile.setId(jsonObject.getInt(context.getString(R.string.profile_id)));
profile.setLastName(jsonObject.getString(context.getString(R.string.profile_lastName)));
profile.setName(jsonObject.getString(context.getString(R.string.profile_name)));
profile.setEmail(jsonObject.getString(context.getString(R.string.profile_email)));
} catch (JSONException | NullPointerException e) {
e.printStackTrace();
return null;
}
return profile;
}
In your onResponse method
#Override
public void onResponse(String response) {
//If you have son object
Profile profile = getUserProfile(response)
}

Adding POST parameters to Android Volley JsonObjectRequest

Good afternoon everyone
I did a volley connection to my localserver. It turns out, the connection works fine but my parameters are not getting accepted in my MysqlPHP script.
I believe the parameters are not getting sent correctly.
Here is the code
try {
RequestQueue jr = Volley.newRequestQueue(this);
HashMap<String, String> params = new HashMap<String, String>();
params.put("username", username);
params.put("password", password);
Log.d("The paramet ready", "Ready to go");
JsonObjectRequest jsonObject = new JsonObjectRequest(Request.Method.POST, url, new JSONObject(params),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("The response", response.toString());
progressDial.hide();
JSONArray json = null;
try {
json = response.getJSONArray("result");
} catch (JSONException e) {
e.printStackTrace();
}
try {
if (json.getString(0).equalsIgnoreCase("0")) {
Log.d("JsonString: -> ", json.toString());
progressDial.hide();
toast();
} else {
startagain();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
progressDial.hide();
}
}
);
jr.add(jsonObject);
I encountered a similar issue. I had a server API which returned a JSON Object response, so JsonObjectRequest was the go-to request type, but the server didn't like that my body was in JSON format, so I had to make a few changes to my request.
Here's what I did (adapted to your code):
JsonObjectRequest jsonObject = new JsonObjectRequest(Request.Method.POST, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("The response", response.toString());
progressDial.hide();
JSONArray json = null;
try {
json = response.getJSONArray("result");
} catch (JSONException e) {
e.printStackTrace();
}
try {
if (json.getString(0).equalsIgnoreCase("0")) {
Log.d("JsonString: -> ", json.toString());
progressDial.hide();
toast();
} else {
startagain();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
progressDial.hide();
}
}
)
{
#Override
public byte[] getBody()
{
try
{
final String body = "&username=" + username + // assumes username is final and is url encoded.
"&password=" + password // assumes password is final and is url encoded.
return body.getBytes("utf-8");
}
catch (Exception ex) { }
return null;
}
#Override
public String getBodyContentType()
{
return "application/x-www-form-urlencoded";
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError
{
Map<String, String> headers = new HashMap<String, String>();
headers.put("Accept", "application/json");
return headers;
}
};
Here, I'm not sending any JSON Object as the post body, but instead, I'm creating the post body on my own, form url encoded.
I'm overriding the following methods:
getBody - I'm creating the body of the post exactly the way the server wanted it - form url encoded.
getBodyContentType - I'm telling the server what the content type of my body is
getHeaders - I'm telling the server to return the result in JSON format. This might not be necessary for you.
If your API return a JSON array, then you should use a JsonArrayRequest, not a JsonRequest.

Categories

Resources