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
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 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));
}
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 am getting wrong response in volley while on the other hand postman getting correct response. Please help me where is the problem . Response i am getting from volley is "response= {"code":1020,"message":"Duplicate key not allowed","returnId":null}"
And in postman it is "{
"code": 1089,"message": "Activation Key sent in email, please activate your user/device","returnId": 438
}"
public void sendRegisterationReq("http://demo.innowi.com/v1/user/register",getJsonObject()) {
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
url, dataObj,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
// Toast.makeText(context, "" + response.toString(), Toast.LENGTH_SHORT).show();
System.out.println("response= " + response.toString());
System.out.println(TAG + ":" + dataObj.toString());
try {
if (response.getString("code").equals("1020")){
Intent intent = new Intent(RegisterDeviceActivity.this,ActivateDeviceActivity.class);
startActivity(intent);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError volleyError) {
String message = null;
if (volleyError instanceof NetworkError) {
message = "Network error!";
Log.d(TAG,message);
} else if (volleyError instanceof ServerError) {
message = "Server error!!";
Log.d(TAG,message);
} else if (volleyError instanceof AuthFailureError) {
message = "Auth failure error!";
Log.d(TAG,message);
} else if (volleyError instanceof ParseError) {
message = "Parsing error!";
Log.d(TAG,message);
} else if (volleyError instanceof NoConnectionError) {
message = "No connection error!";
Log.d(TAG,message);
} else if (volleyError instanceof TimeoutError) {
message = "timeout error !";
Log.d(TAG,message);
}
/*Toast.makeText(context, "error", Toast.LENGTH_SHORT).show();
System.out.println(TAG + ":Error: " + volleyError.getMessage());
System.out.println(TAG + ":" + volleyError.toString());*/
System.out.println(TAG + ":" + dataObj.toString());
}
}) {
/**
* Passing some request headers
* */
#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.setTag("myRequest");
// Adding request to request queue
queue.add(jsonObjReq);
}
public JSONObject getJsonObject(){
JSONObject object = new JSONObject();
try {
if (username!=null && password !=null) {
object.put("username", username.getText().toString());
object.put("password", password.getText().toString());
object.put("deviceMacAddress", "90:B6:86:0D:CE:4F");
}
else
{
Toast.makeText(this, "Email/password should not be empty", Toast.LENGTH_SHORT).show();
}
} catch (JSONException e) {
e.printStackTrace();
}
return object;
}
you are the data which is already exist in your database so says duplicate key try different one or try to send all fields valid and different.
I am trying to use volley to fetch my product list on my WordPress store using Rest API HTTP basic Auth but it keeps returning error 401 unauthorized.
This is my code:
private void getProducts() {
Log.d(TAG, "getProducts called");
String url = "https://www.mystoreurl.com/wp-json/wc/v1/products";
mJsonArrayRequest = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, "onResponse called with " + response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "onErrorResponse called for getProducts");
NetworkResponse errorResponse = error.networkResponse;
if (errorResponse != null && errorResponse.data != null) {
String statusCode = String.valueOf(errorResponse.statusCode);
Log.d(TAG, "Status code is " + statusCode);
String fullMessage = new String(errorResponse.data);
Log.w(TAG, "Error message is " + fullMessage);
}
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
String key = getString(R.string.store_consumer_Key);
String secret = getString(R.string.store_consumer_secret);
headers.put("consumer_key", key);
headers.put("consumer_secret", secret);
return headers;
}
};
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
requestQueue.add(mJsonArrayRequest);
}
However, if I put the consumer key and secret as parameters in the url like this:
private void getProducts() {
Log.d(TAG, "getProducts called");
String key = getString(R.string.store_consumer_Key);
String secret = getString(R.string.store_consumer_secret);
String url = "https://www.mystoreurl.com/wp-json/wc/v1/products?consumer_key=" + key + "&consumer_secret=" + secret;
mJsonArrayRequest = new JsonArrayRequest(url, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, "onResponse called with " + response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d(TAG, "onErrorResponse called for getProducts");
NetworkResponse errorResponse = error.networkResponse;
if (errorResponse != null && errorResponse.data != null) {
String statusCode = String.valueOf(errorResponse.statusCode);
Log.d(TAG, "Status code is " + statusCode);
String fullMessage = new String(errorResponse.data);
Log.w(TAG, "Error message is " + fullMessage);
}
}
});
RequestQueue requestQueue = Volley.newRequestQueue(getActivity());
requestQueue.add(mJsonArrayRequest);
}
It works, but I am concerned about security. Please is this secure? If not, then how can I authenticate through the headers?