I tested my REST service in POSTMAN and it works. I should get something like this:
{
"msg": "the user was successfully created"
...
}
but in my android app in debug cannot find the response. Have I missed something or am I doing something wrong? Thanks!
private void registerUser(final String firstName, final String lastName,
final String email, final String password) {
pDialog.setMessage("Registering ...");
showDialog();
try {
RequestQueue requestQueue = Volley.newRequestQueue(this);
JSONObject jsonBody = new JSONObject();
jsonBody.put("first_name", firstName);
jsonBody.put("last_name", lastName);
jsonBody.put("email", email);
jsonBody.put("password", password);
final String requestBody = jsonBody.toString();
StringRequest stringRequest = new StringRequest(Request.Method.POST, AppConfig.URL_REGISTER, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d(TAG, "Register Response: " + response);
hideDialog();
...
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("VOLLEY", error.toString());
}
}) {
#Override
public String getBodyContentType() {
return "application/json";
}
#Override
public byte[] getBody() throws AuthFailureError {
try {
return requestBody == null ? null : requestBody.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s", requestBody, "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();
}
In debug, the block
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
String responseString = "";
if (response != null) {
responseString = String.valueOf(response.statusCode);
}
return Response.success(responseString, HttpHeaderParser.parseCacheHeaders(response));
}
displays this:
I have no JSON response.
You don't see any json data because you are not generating any json response from you side. The response you see on Postman is from the api service. You have a success response from your program (i.e. Status code 201) and that's the only thing you are sending back to the client.
if (response != null) {
responseString = String.valueOf(response.statusCode);
}
You have to manipulate the response (in parseNetworkResponse module) and forward the relevant info you want to your client.
Related
I am trying to create the Android version of a curl GET request. Works great in terminal, but fails in the app.
The curl request (urls are not real):
curl -d '{"detail": "Y"}' -H "Content-Type:application/json" -X GET -H "Auth-Token:longstringhereforauthtoken" https://api.myendpoint.com/REST/GSLB/zone-to-get-records-from.com/fqdn-of-domain.com/
It gives back what I need without any issue.
Well, now I want to use that request in a Volley request in Android, however, I am getting back:
Unexpected response code 406 for https://api.myendpoint.com/REST/GSLB/zone-to-get-records-from.com/fqdn-of-domain.com/
The code where I'm attempting the request is as follows (will show relevant variables that are set beforehand):
private String url;
private String request;
private String searchRequest;
String selected = getIntent().getStringExtra("node");
String token = getIntent().getStringExtra("token");
url = getResources().getString(R.string.api_url);
request = url + "/Session/";
searchRequest = url + "/GSLB/"+selected+"/"+selected+"/";
ProgressDialog searchDialog = new ProgressDialog(MainActivity.this);
searchDialog.setMessage("Getting zone info...");
searchDialog.show();
JSONObject object = new JSONObject();
try {
object.put("Content-Type", "application/json");
object.put("Auth-Token", token);
object.put("detail", "Y");
} catch(JSONException e) {
Log.d(TAG, e.getMessage());
}
Log.d(TAG, "Selected "+icon+", Token: "+token);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, searchRequest, object,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
searchDialog.dismiss();
Log.d(TAG, String.valueOf(response));
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
searchDialog.dismiss();
if( error instanceof NetworkError) {
Log.d(TAG, error.toString());
Log.d(TAG, "Request to "+searchRequest+" FAILED...");
} else if( error instanceof ServerError) {
Log.d(TAG, "Request to "+searchRequest+" FAILED...");
Log.d(TAG, error.toString());
} else if( error instanceof AuthFailureError) {
Log.d(TAG, error.toString());
Log.d(TAG, "Request to "+searchRequest+" FAILED...");
} else if( error instanceof ParseError) {
Log.d(TAG, error.toString());
Log.d(TAG, "Request to "+searchRequest+" FAILED...");
} else if( error instanceof NoConnectionError) {
Log.d(TAG, error.toString());
Log.d(TAG, "Request to "+searchRequest+" FAILED...");
} else if( error instanceof TimeoutError) {
Log.d(TAG, error.toString());
Log.d(TAG, "Request to "+searchRequest+" FAILED...");
}
}
});
RequestQueue searchRequestQueue = Volley.newRequestQueue(MainActivity.this);
searchRequestQueue.add(jsonObjectRequest);
That is when I receive the error:
BasicNetwork.performRequest: Unexpected response code 406 for https://api.myendpoint.com/REST/GSLB/zone-to-get-records-from.com/fqdn-of-domain.com/
Before this activity, I have a LoginActivity that does a similar request, which is where the token comes from in the GET request. It sends credentials and received the Auth-Token. This one works, so I am unsure of why the previous snippet is failing.
The Login request:
JSONObject object = new JSONObject();
try {
object.put("user_name", usernameEditText.getText().toString());
object.put("customer_name", customernameEditText.getText().toString());
object.put("password", passwordEditText.getText().toString());
object.put("Content-Type", "application/json");
} catch(JSONException e) {
Log.d(TAG, e.getMessage());
}
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, request, object,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
if(response != null) {
Log.d("JSON", String.valueOf(response));
String token = null;
pDialog.dismiss();
try {
token = response.getJSONObject("data").getString("token");
Log.d("JSON", token);
} catch (JSONException e) {
Toast.makeText(LoginActivity.this, "" + e.getMessage(),Toast.LENGTH_LONG).show();
e.printStackTrace();
}
Intent loginIntent = new Intent(LoginActivity.this, SelectActivity.class);
loginIntent.putExtra("token", token);
LoginActivity.this.startActivity(loginIntent);
} else {
Toast nullToast = Toast.makeText(LoginActivity.this, "Invalid Credentials\nPlease try again", Toast.LENGTH_LONG);
nullToast.show();
usernameEditText.getText().clear();
customernameEditText.getText().clear();
passwordEditText.getText().clear();
}
}
}
I have done these requests in both PHP and cURL, but can't seem to understand why it's failing with Android. I feel like my syntax is correct, but perhaps I'm missing something?
The clue was in the request response error code (406). Instead of this:
JSONObject object = new JSONObject();
try {
object.put("Content-Type", "application/json");
object.put("Auth-Token", token);
object.put("detail", "Y");
} catch(JSONException e) {
Log.d(TAG, e.getMessage());
}
I used the getHeaders() method to send my headers, like so:
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/json");
params.put("Auth-Token", token);
params.put("detail", "Y");
return params;
}
Though I do not understand why my object.put() does not work (It was in any tutorials I viewed, so I need to research more), this was what fixed it. I'm now getting my response successfully.
406 http error code stays for "not acceptable". This means that your request has an incorrect header. I believe that JsonObjectRequest doesn't manage headers, but the request body.
In order to work on request header you need to override the getHeaders() method from VolleyRequest class, something like:
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/json");
params.put("Auth-Token", token);
params.put("detail", "Y");
return params;
}
I made a Custom JSONObjectRequest as below code.
Currently i made the Request.Method.POST and i had confirmed it while passing to the super class here
super(method, url, (jsonRequest == null) ? null : jsonRequest.toString(), listener, errorListener);. It was received as int 1 (POST), but when received on my server (PHP), the log was receiving as "REQUEST_METHOD":"GET"
Have anyone met this kind of problem or can help to point out what i had missed in below code.
As you can see below, i had make sure below things:
params not empty
there is function getParams() there and the params are not empty
i even put getBody() and make sure it not returning null
Refer below code for what i had tried to do
try {
JsonObjectRequest stringRequest = new JsonObjectRequest(Request.Method.POST, url, params, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject jsonObject) {
if (jsonObject != null && jsonObject.length() > 0) {
try {
if (jsonObject.getInt("status") == ResponseCode.LOGIN_FAILED) {
SharedManager sharedManager = new SharedManager();
sharedManager.logoutUser(context, true);
return;
}
} catch (JSONException e) {
e.printStackTrace();
}
}
callback.onSuccessResponse(jsonObject);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
callback.onErrorResponse(error);
}
}) {
/**
* Passing some request headers
* */
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers;
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
try {
return JSONHelperConverter.jsonToMapString(params);
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8;";
}
#Override
public byte[] getBody() {
try {
String postBody = null;
try {
postBody = createPostBody(JSONHelperConverter.toMapString(params));
postBody = params.toString();
} catch (JSONException e) {
e.printStackTrace();
}
return postBody == null ? null : postBody.getBytes("utf-8");
} catch (NegativeArraySizeException n) {
n.printStackTrace();
return null;
} catch (UnsupportedEncodingException uee) {
uee.printStackTrace();
return null;
}
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
String responseString;
JSONObject jsonObject = null;
if (response != null) {
try {
responseString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
jsonObject = new JSONObject(responseString);
} catch (Exception e) {
e.printStackTrace();
}
}
return Response.success(jsonObject, HttpHeaderParser.parseCacheHeaders(response));
}
};
NetworkSingleton.getInstance(context).addToRequestQueue(stringRequest);
} catch (NegativeArraySizeException n) {
n.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
I solved my own problem
Sent POST request but server says GET request in Android volley, what I am doing wrong here?
Solution:
Due to i'm requesting to PHP server, i need to point out the filename.
Currently i point the request to a URL without Filename extension, and i just add index.php to my end of URL and it worked.
I'm testing the inter media API and I am trying it using this code below. I used volley for this:
String url = "https://api.infermedica.com/v2/diagnosis";
JSONArray evidence = new JSONArray();
JSONObject evidence1 = new JSONObject();
try {
evidence1.put("id", "s_1193");
evidence1.put("choice_id", "present");
} catch (JSONException e) {
e.printStackTrace();
}
try {
evidence.put(0,evidence1);
} catch (JSONException e) {
e.printStackTrace();
}
JSONObject postparams = new JSONObject();
try {
postparams.put("sex", "male");
postparams.put("age", 30);
postparams.put("evidence", evidence);
} catch (JSONException e) {
e.printStackTrace();
}
Log.e("DATA:", postparams.toString());
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
url, postparams,
new Response.Listener() {
#Override
public void onResponse(Object response) {
Log.e("DATA: ", response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// As of f605da3 the following should work
NetworkResponse response = error.networkResponse;
if (error instanceof ServerError && response != null) {
try {
String res = new String(response.data,
HttpHeaderParser.parseCharset(response.headers, "utf-8"));
// Now you can use any deserializer to make sense of data
JSONObject obj = new JSONObject(res);
Log.e("DATA:" , obj.toString());
} catch (UnsupportedEncodingException e1) {
// Couldn't properly decode data to string
e1.printStackTrace();
} catch (JSONException e2) {
// returned data is not JSONObject?
e2.printStackTrace();
}
}
}
}
) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("app-id", "MY-APP-ID");
headers.put("app-key", "MY-APP-KEY");
headers.put("authorization", "Basic Og==");
headers.put("Content-type", "application/json");
return headers;
}
};
Log.e("DATA: " , "calling volley");
RequestQueue requestQueue = Volley.newRequestQueue(this);
requestQueue.add(jsonObjReq);
After running it and checking the logs here is the result:
E/DATA:: {"sex":"male","age":30,"evidence":
[{"id":"s_1193","choice_id":"present"}]}
E/DATA:: calling volley
E/Volley: [236] BasicNetwork.performRequest: Unexpected response code 400
for https://api.infermedica.com/v2/diagnosis
E/DATA:: {"message":"bad request"}
I tried the logged json in Postman and it was accepted:
Here is the screenshot of my postman result
I've been looking for answers around here, I already added the content-type, and I made sure that my keys are correct. Am I using the volley correctly. Your help will be much appreciated.
I don't know how I can set a header "Accept" for 'applicatjon/json now my response from server is a xml but I want to have a json. A server should send me a xml when I set a header. This is my code :
final JSONObject requestObject = new JSONObject();
try {
requestObject.put("company", "TEST");
requestObject.put("user", "pawelo");
requestObject.put("secure_password", "8ce241e1ed84937ee48322b170b9b18c");
requestObject.put("secure_device_id", "C4CA4238A0B923820DCC509A6F75849B");
} catch (JSONException e) {
e.printStackTrace();
}
StringEntity entity = null;
try {
entity = new StringEntity(requestObject.toString());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
entity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
client.post(this, url, entity, "application/json",
new BaseJsonHttpResponseHandler("UTF-8") {
#Override
public void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, Object response) {
Log.e("sdasa " , rawJsonResponse + " " + statusCode);
}
#Override
public void onFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, Object errorResponse) {
}
#Override
protected Object parseResponse(String rawJsonData, boolean isFailure) throws Throwable {
return null;
}
});
JSONObject json = new JSONObject();
JSONObject dataJson = new JSONObject();
dataJson.put("body", message);
dataJson.put("title", getFirebaseUser().getDisplayName());
json.put("notification", dataJson);
json.put("registration_ids",jsonArray);
StringEntity se = new StringEntity(json.toString(), "UTF-8");
AsyncHttpClient client = new AsyncHttpClient();
client.addHeader("Accept", "application/json");
client.addHeader("Content-type", "application/json;charset=utf-8");
client.addHeader("Authorization", "key=" + "xxxxxxxxxxxx");
client.post(getInstance(), "your url", se, "application/json;charset=utf-8", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(int statusCode, Header[] headers, byte[] responseBody) {
Log.e("success_noti", new String(responseBody) + "");
if(isEnd){
getMessage.getMessageFunc(END);
}
}
#Override
public void onFailure(int statusCode, Header[] headers, byte[] responseBody, Throwable error) {
Log.e("fail_noti", new String(responseBody) + "");
}
});
Using AsyncHttpClient Library This is also another approach.
You can Add accept line on header when you are sending request to server.
URL url;
HttpURLConnection urlConnection = null;
String response = null;
InputStream in = null;
try {
url = new URL(urlStr);
urlConnection = (HttpURLConnection) url.openConnection();
/* optional request header */
urlConnection.setRequestProperty("Content-Type", "application/json");
/* optional request header */
urlConnection.setRequestProperty("Accept", "application/json");
urlConnection.setRequestMethod("GET");
//InputStream in = urlConnection.getInputStream();
int statusCode = urlConnection.getResponseCode();
/* 200 represents HTTP OK */
if (statusCode == 200) {
in = new BufferedInputStream(urlConnection.getInputStream());
response = Utils.convertInputStreamToString(in);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (urlConnection != null) {
urlConnection.disconnect();
}
}
use this code
public String POST(String url, Been been){
InputStream inputStream = null;
String result = "";
try {
HttpPost httpPost = new HttpPost(url);
String json = "";
JSONObject jsonObject = new JSONObject();
jsonObject.accumulate("company", Been.getcompany());
jsonObject.accumulate("user", Been.getuser());
jsonObject.accumulate("secure_password", Been.getpassword());
jsonObject.accumulate("secure_device_id", Been.getdevice_id());
json = jsonObject.toString();
StringEntity se = new StringEntity(json);
httpPost.setEntity(se);
httpPost.setHeader("Accept", "application/json");
httpPost.setHeader("Content-type", "application/json");
HttpResponse httpResponse1 = httpclient.execute(httpPost);
inputStream = httpResponse1.getEntity() .getContent();
if(inputStream != null)
result = convertInputStreamToString(inputStream);
else
result = "Did not work!";
} catch (Exception e) {
Log.d("InputStream", e.getLocalizedMessage());
}
return result;
}
use AsyncTask to call method
public class HttpAsyncTask extends AsyncTask<Void, Void, String> {
private ProgressDialog mProgressDialog;
private DefaultHttpClient httpclient;
private HttpPost httppost;
#Override
protected String doInBackground(Void... params) {
httpclient = new DefaultHttpClient();
//Create new HTTP POST with URL to php file as parameter
httppost = new HttpPost(url);
Been = new Been();
Been.setcompany("TEST");
Been.setuser("pawelo");
Been.setpassword("8ce241e1ed84937ee48322b170b9b18c");
Been.setdevice_id("C4CA4238A0B923820DCC509A6F75849B");
return POST(url, Been);
}
#Override
protected void onPostExecute(String result) {
mProgressDialog.dismiss();
}
#Override
protected void onPreExecute() {
mProgressDialog = ProgressDialog.show(getActivity(), "", "loading...");
mProgressDialog.setCancelable(false);
mProgressDialog.setCanceledOnTouchOutside(false);
}
}
Create Boon class
public class Been {
private String name;
private String user;
private String password;
private String device_id;
public String getcompany() {
return name;
}
public void setcompany(String name1) {
this.name= name1;
}
public String getuser() {
return user;
}
public void setuser(String user1) {
this.user= user1;
}
public String getpassword() {
return user;
}
public void setpassword(String password1) {
this.password= password1;
}
public String getdevice_id() {
return user;
}
public void setdevice_id(String device_id1) {
this.device_id= device_id1;
}
}
I am making a Json request and I get the data and place it in a list view but some of the strings i get have accents or 'ç' and it doesn't appear correctly.
For example, the string is 'Bragança' and i receive 'Bragança' or 'à' and get 'Ã'. If i do the request in the browser, all works properly.
My request.
public void makeJsonArrayRequest() {
RequestQueue queue = AppController.getInstance().getRequestQueue();
queue.start();
JsonArrayRequest Req = new JsonArrayRequest(urlJsonObjUtilizadas,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d(TAG, response.toString());
// Parsing json
for (int i = 0; i < response.length(); i++) {
try {
JSONObject ementaObj = response.getJSONObject(i);
Ementa ementa = new Ementa();
ementa.setCantina(ementaObj.getString("cantina"));
ementa.setDescricao(ementaObj.getString("descricao"));
ementa.setEmenta(ementaObj.getString("ementa"));
ementa.setPreco(ementaObj.getInt("preco"));
ementaItems.add(ementa);
} catch (JSONException e) {
e.printStackTrace();
}
}
// notifying list adapter about data changes
adapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d(TAG, "Error: " + error.getMessage());
}
}) {
//**
// Passing some request headers
//*
#Override
public Map<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json; charset=UTF-8");
return headers;
}
};
// Add the request to the RequestQueue.
AppController.getInstance().addToRequestQueue(Req);
}
I think this is because of the wrong content type encoding header. You are supposed to use UTF-8 as encoding. Maybe this is working in the browsers because the headers are not case-sensitive (unlike Android).
Take a look here for a solution. Essentially they are manually overriding the charset.
please try to use this code for sending and receiving JSON with utf-8 encoding:
try {
URL url = new URL("your url");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(
conn.getOutputStream(), "UTF-8");
String request = "your json";
writer.write(request);
writer.flush();
System.out.println("Code:" + conn.getResponseCode());
System.out.println("mess:" + conn.getResponseMessage());
String response = "";
BufferedReader reader = new BufferedReader(new InputStreamReader(
conn.getInputStream(), "UTF-8"));
String line;
while ((line = reader.readLine()) != null) {
response += line;
}
System.out.println(new String(response.getBytes(), "UTF8"));
writer.close();
reader.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
You should add the request header charset to UTF-8. For example if your request will be as json, you should add this header to the request:
"Content-type": "Aplicación/json; utf-8"
I use Volley too and this way works for me.
Regards.
Check this sample, this way i am using, look the header section
public class Estratek_JSONString extends JsonRequest<String>{
Activity Act;
Priority priority;
public Estratek_JSONString(int m, String url, JSONObject params,
Listener<String> listener, ErrorListener errorListener,Activity act, Priority p) {
super(m,url,params.toString(),listener,errorListener);
this.Act=act;
this.priority=p;
}
public Estratek_JSONString(int m, String url,
Listener<String> listener, ErrorListener errorListener,Activity act, Priority p) {
// super constructor
//super(m,url,params.toString(),listener,errorListener);
super(m,url,null,listener,errorListener);
this.Act=act;
this.priority=p;
}
#Override
public Map<String, String> getHeaders() {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Content-Type", "application/json; charset=utf-8");
headers.put("Authorization", "Bearer "+Tools.Get_string(Act.getApplicationContext(),Global_vars.Access_token));
return headers;
}
//it make posible send parameters into the body.
#Override
public Priority getPriority(){
return priority;
}
#Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString =
new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(new String(jsonString),
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
}