I'm trying to do an HTTP PUT with JSON to a service that needs HTTP Basic Auth, but I keep getting client errors. I do this:
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.PUT, payOp.getURL(), payOp.getJson(), new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i("jsonObjectRequest", "Response " + response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i("jsonObjectRequest", "Error " + error.toString());
Log.i("jsonObjectRequest", "Error ", error);
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
ApplicationSettings applicationSettings = ApplicationSettings.getInstance();
String username = applicationSettings.mMID;
String password = applicationSettings.mAPIPassword;
String creds = String.format("%s:%s",username, password);
String auth = "Basic " + Base64.encodeToString(creds.getBytes(), Base64.NO_WRAP);
Log.i("jsonObjectRequest","Authorization is: " + auth);
params.put("Authorization", auth);
return params;
}
};
queue.add(jsonObjectRequest);
And I get back:
2019-05-04 17:52:40.158 7430-7430/com.amex.gatewaydemotr5 I/jsonObjectRequest: Error
com.android.volley.ClientError
at com.android.volley.toolbox.BasicNetwork.performRequest(BasicNetwork.java:199)
at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:131)
at com.android.volley.NetworkDispatcher.processRequest(NetworkDispatcher.java:111)
at com.android.volley.NetworkDispatcher.run(NetworkDispatcher.java:90)
I can't figure out what I'm doing wrong. I'm making the creds string correct (I have another app written in node.js that works to compare the output to) but I don't get a lot of output from Volley for an error. Can anyone see what I'm doing wrong? Is there some way to get more detail out of Volley on the error? Thanks!
Ok, figured it out. It was a problem with my URL & Data, but the main thing was I didn't understand how to parse the errors, for anyone who needs to know there's a networkResponse object on the error that has statusCode and data parameters. The server messages are there. The data parameter comes back as a byte array, so you have to wrap it in a string object to see the results.
Once I understood that I could get the messages back I needed and fix the problem, here's the code:
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.PUT, payOp.getURL(), payOp.getJson(), new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.i("jsonObjectRequest", "Response " + response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i("jsonObjectRequest", "Error, Status Code " + error.networkResponse.statusCode);
Log.i("jsonObjectRequest", "URL: " + payOp.getURL());
Log.i("jsonObjectRequest", "Payload: " + payOp.getJson().toString());
Log.i("jsonObjectRequest", "Net Response to String: " + error.networkResponse.toString());
Log.i("jsonObjectRequest", "Error bytes: " + new String(error.networkResponse.data));
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> params = new HashMap<String, String>();
ApplicationSettings applicationSettings = ApplicationSettings.getInstance();
String username = applicationSettings.mMID;
String password = applicationSettings.mAPIPassword;
String creds = String.format("%s:%s",username, password);
String auth = "Basic " + Base64.encodeToString(creds.getBytes(), Base64.NO_WRAP);
Log.i("jsonObjectRequest","Authorization is: " + auth);
params.put("Authorization", auth);
return params;
}
};
The important part is this:
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i("jsonObjectRequest", "Error, Status Code " + error.networkResponse.statusCode);
Log.i("jsonObjectRequest", "URL: " + payOp.getURL());
Log.i("jsonObjectRequest", "Payload: " + payOp.getJson().toString());
Log.i("jsonObjectRequest", "Net Response to String: " + error.networkResponse.toString());
Log.i("jsonObjectRequest", "Error bytes: " + new String(error.networkResponse.data));
}
Related
The following Android Volley GET Request is failing with the following error message:
E/Volley: [1038] BasicNetwork.performRequest: Unexpected response code 401 for
This is the Request:
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
final String url = "https://xxxxxxxx/storage/v1/items";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET,url, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
StringBuilder formattedResult = new StringBuilder();
JSONArray responseJSONArray = response.getJSONArray("items");
for (int i = 0; i < responseJSONArray.length(); i++) {
formattedResult.append("\n" + responseJSONArray.getJSONObject(i).get("no") + "=> \t" + responseJSONArray.getJSONObject(i).get("ean")
+ "=> \t" + responseJSONArray.getJSONObject(i).get("name")
+ "=> \t" + responseJSONArray.getJSONObject(i).get("type")
+ "=> \t" + responseJSONArray.getJSONObject(i).get("destruction")
+ "=> \t" + responseJSONArray.getJSONObject(i).get("archived")
);
}
txtShowTextResult.setText("List of Items \n" + " Number" + "\t EAN \n" +
"\t Name \n" + "\t Type \n" + formattedResult);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
txtShowTextResult.setText("An Error occured while making the request");
}
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
String credentials = "username:password";
String auth = "Basic "
+ Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
headers.put("Content-Type", "application/json");
headers.put("Authorization", auth);
return headers;
}
});
requestQueue.add(jsonObjectRequest);
I am not sure why the Request is failing, as I am new to Android Volley.
Possible cause: the method getHeaders() is not called, but I donĀ“t know where to put the Method call in the Request and therefore, I would appreciate any help, hints or feedback. Thanks in advance!
Adding the missing part at your code you can try out the following. Notice the override part of getHeaders, let me know how it goes.
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, url, null,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
//handle response
}
}
, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
//handle error
}
}){
#NotNull
#Override
public Map<String, String> getHeaders() {
//Handle headers inside here
Map<String, String> headers = new HashMap<>();
String credentials = "username:password";
String auth = "Basic "
+ Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
headers.put("Content-Type", "application/json");
headers.put("Authorization", auth);
return headers;
}
};
requestQueue.add(jsonObjectRequest);
I'm trying to make a POST request to get token from my web API (writen by asp.net mvc) and it works in Postman (I get a valid JSON object), but not using Volley. With the following code:
String url = "https://branj.ir/Token";
Response.Listener<String> listener= new Response.Listener<String>() {
#Override
public void onResponse(String jsonResult) {
Log.i(G.Tag, "volley result: " + jsonResult);
}
};
Response.ErrorListener errorListener= new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
Log.d(G.Tag, "Error: " + error
+ "\nStatus Code " + error.networkResponse.statusCode
+ "\nCause " + error.getCause()
+ "\nmessage" + error.getMessage());
}
};
StringRequest request = new StringRequest (
Request.Method.POST,
url,
listener,
errorListener
)
{
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String,String> params = new HashMap<String, String>();
params.put("Content-Type","application/x-www-form-urlencoded");
params.put("Accept", "application/json");
return params;
} }
;
logcat is:
BasicNetwork.performRequest: Unexpected response code 400 for https://branj.ir/Token
11-13 16:55:59.608 21200-21200/ir.branj.app.wideidea.ir.branj D/Branj: Error: com.android.volley.ClientError
Status Code 400
Cause null
messagenull
I changed the application code as follows and my problem was resolved
public static void Token(final String username, final String password) {
String url = BASE_URL + "Token";
Response.Listener<String> listener= new Response.Listener<String>() {
#Override
public void onResponse(String jsonResult) {
Log.i(G.Tag, "volley result: " + jsonResult);
}
};
Response.ErrorListener errorListener= new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
Log.d(G.Tag, "Error: " + error
+ "\nStatus Code " + error.networkResponse.statusCode
+ "\nCause " + error.getCause()
+ "\nnetworkResponse " + error.networkResponse.data.toString()
+ "\nmessage" + error.getMessage());
}
};
StringRequest request = new StringRequest (
Request.Method.POST,
url,
listener,
errorListener
)
{
#Override
public Map<String, String> getParams() throws AuthFailureError {
Map<String,String> params = new HashMap<>();
params.put("username", username);
params.put("password", password);
params.put("grant_type", "password");
return params;
}
} ;
G.getInstance().addToRequestQueue(request);
}
{
"error": "unsupported_grant_type"
}
when i have used your request on postman i am getting the error because the body is incorrect of the volley.
I've developed a REST webservice and consume it by android client.
The webservice works fine but sometimes android volley got a com.android.volley.ServerError. If I check the url with postman everything works. This problem is just by some few users and I cannot reproduce the error.
Here is my Volley request:
public void requestURL(final RestCallback callback) {
Log.d("JSON", url);
JsonArrayRequest jsonObjectRequest = new JsonArrayRequest
(Request.Method.GET, url, null, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
callback.onSuccess(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("JSON", "onErrorResponse: " + url);
String errorText = null;
if (error instanceof TimeoutError || error instanceof NoConnectionError) {
Log.d("Error", "Timeouterror");
errorText = context.getString(R.string.error_timeout);
} else if (error instanceof ServerError) {
Log.d("Error", "Servererror");
errorText = context.getString(R.string.error_server);
} else if (error instanceof NetworkError) {
Log.d("Error", "Servererror");
errorText = context.getString(R.string.error_network);
} else if (error instanceof ParseError) {
Log.d("Error", "Parseerror");
errorText = context.getString(R.string.error_parse);
}
Crashlytics.logException(new Throwable("Errornachricht: " + error.getMessage() + " Error: " + error.toString() + "\n URL: " + url + "\n Cause: " +error.getCause() + " Stacktrace: " + error.getStackTrace()));
callback.onError(errorText);
}
}) {
#Override
public Map<String, String> getHeaders() {
return Security.getAuth();
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
return super.getParams();
}
};
RequestQueue requestQueue = Volley.newRequestQueue(context);
//sets time for retry connection
jsonObjectRequest.setRetryPolicy(new DefaultRetryPolicy( 0, DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
jsonObjectRequest.setShouldCache(false);
//Adding request to the queue
requestQueue.add(jsonObjectRequest);
}
And the method getAuth which is called bei getHeaders:
public static Map<String, String> getAuth() {
String credentials = "username" + ":" + "password";
String base64EncodedCredentials = Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);
HashMap<String, String> headers = new HashMap<>();
headers.put("Accept","application/json");
headers.put("Content-Type","application/json");
headers.put("Authorization", "Basic " + base64EncodedCredentials);
return headers;
}
Error log:
Has anybody an idea why I got this error?
I think some times API response is not a valid JsonArray, at that time it will throw a server error. API response is a "null" or a jsonObject like wise
I am using volley JsonObjectRequest, I getting json response for some json format and getting 400 response code for some format.
Json format
{
"errors": "This password is too short. It must contain at least 8 characters & Please provide a valid id type",
"message": "Account could not be created with received data.",
"status": "Bad request"
}
volley call
public void userRegistraion(String identifier, String password, String idType){
final String URL = "https://someweb.com/auth/user/registration/";
//Post params to be sent to the server
JSONObject params = new JSONObject();
try {
params.put("identifier", identifier);
params.put("password", password);
params.put("id_type", idType);
}catch (JSONException e){
e.printStackTrace();
}
JsonObjectRequest request_json = new JsonObjectRequest(Request.Method.POST,URL,params,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("volley response",response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("volley", "Error: " + error
+ "\nStatus Code " + error.networkResponse.statusCode
+ "\nResponse Data " + error.networkResponse.data
+ "\nResponse header " + error.networkResponse.headers
+ "\nCause " + error.getCause()
+ "\nmessage" + error.getMessage());
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
return headers;
}
#Override
public String getBodyContentType() {
return "application/json";
}
};
// add the request object to the queue to be executed
Myapplication.getInstance().addToRequestQueue(request_json);
}
Error:
E/Volley: [74123] BasicNetwork.performRequest: Unexpected response code 400 for https://someweb.com/auth/user/registration/
but no error is coming for this json type with the same request.
{"user":{"th_user_id":"KSJDYDYD",
"is_active":true,
"is_verified":false,
"role":"user",
"created_at":"2018-03-21T06:25:02.556490Z",
"updated_at":"2018-03-1T06:25:02.556516Z",
"verified_at":null,"last_login":"2018-03-21T06:25:02.570251Z",
"documents":[]},
"token":"11f2faea30847db4u3hfhu0384hh392dac46"}
The 400 Bad Request error is an HTTP status code that means that the JsonObjectRequest request you sent to the api endpoint in your server was incorrect or corrupted and the server couldn't understand it.
I would suggest you let your php file report all error like this so that you get more information about this error
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
Ways to implement volley json response cache.I tried the following way to get response from volley.i get the response correctly.I dont know how to store these json values into volley cache
StringRequest strReq = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
System.out.println("mainresp$$$"+response);
Log.d("Volley Request Success", response.toString());
result=response;
callback.onSuccess(result);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("volley request Error",
"Error: " + error.getMessage());
}
}) {
#Override
protected Map<String, String> getParams() {
return params;
}
};
// Adding request to request queue
AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
Together with my comments, you have already read my answer at the following question:
Android Setup Volley to use from Cache
I have just tested with POST request, as the following code:
CacheRequest cacheRequest = new CacheRequest(Request.Method.POST, url, new Response.Listener<NetworkResponse>() {
#Override
public void onResponse(NetworkResponse response) {
try {
final String jsonString = new String(response.data,
HttpHeaderParser.parseCharset(response.headers));
// Check if it is JSONObject or JSONArray
Object json = new JSONTokener(jsonString).nextValue();
JSONObject jsonObject = new JSONObject();
if (json instanceof JSONObject) {
jsonObject = (JSONObject) json;
} else if (json instanceof JSONArray) {
jsonObject.put("success", json);
} else {
String message = "{\"error\":\"Unknown Error\",\"code\":\"failed\"}";
jsonObject = new JSONObject(message);
}
textView.setText(jsonObject.toString(5));
} catch (UnsupportedEncodingException | JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// do something...
}
});
My sample Asp.Net Web API code as the following:
// POST api/<controller>
public IHttpActionResult Post()
{
string jsonString = "[" +
"{" +
"name: \"Person 1\"," +
"age: 30," +
"type: \"POST\"," +
"}," +
"{" +
"name: \"Person 2\"," +
"age: 20," +
"type: \"POST\"," +
"}," +
"{" +
"name: \"Person 3\"," +
"age: 40," +
"type: \"POST\"," +
"}" +
"]";
JArray jsonObj = JArray.Parse(jsonString);
return Ok(jsonObj);
}
Here is the result screenshot