This is the first time I'm working with JSON but I'm experimenting with POST requests.
I want to make a POST request to this website http://jsonblob.com/api
My code works when I use an asynctask + httppost
private static final String url = "http://jsonblob.com/api/jsonBlob";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new PostJsonTask().execute();
}
private class PostJsonTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
try {
HttpResponse response = post();
Header s = response.getFirstHeader("Location");
Log.d("PostJsonTask", s.getValue());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private HttpResponse post() throws Exception {
// convert parameters into JSON object
Map<String, String> params = new HashMap<String, String>();
params.put("user", "Robby");
params.put("pass", "zqdqzdqdqzd");
JSONObject holder = new JSONObject(params);
HttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url);
StringEntity se = new StringEntity(holder.toString());
se.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setHeader("Accept", "application/json");
post.setHeader("Content-type", "application/json");
post.setEntity(se);
return client.execute(post);
}
}
With this code I can succesfully get the Location parameter.
But I want to do this with the Volley library, I already have the following code :
private static final String url = "http://jsonblob.com/api/jsonBlob";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RequestQueue queue = Volley.newRequestQueue(this);
StringRequest request = new StringRequest(Request.Method.POST, url, createResponseListener(), createErrorListener()) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<String, String>();
headers.put("Accept", "application/json");
headers.put("Content-type", "application/json");
return headers;
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("user", "Robby");
params.put("pass", "zqdqzdqdqzd");
return params;
}
#Override
protected Response<String> parseNetworkResponse(
NetworkResponse response) {
Map<String, String> headers = response.headers;
String location = headers.get("Location");
Log.d("PostJsonTask", location);
return super.parseNetworkResponse(response);
}
};
queue.add(request);
}
private ErrorListener createErrorListener() {
return new ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
error.printStackTrace();
}
};
}
private Listener<String> createResponseListener() {
return new Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("PostJsonTask", response);
}
};
}
But this returns a VolleyError with code 400. How can I fix this?
Instead of trying to set Content-type of header try to set for bodyContentType and in postman(web) also you are setting the content type of body only
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.POST,
url, obj,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("Response", response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("Error", error.toString());
}
})
#Override
public String getBodyContentType() {
return "application/json";
}
};
Don't use the getParams override.
Instead, create a JSON with these parameter and provide as the body of the request like they do in JsonObjectRequest (or just use a JsonObjectRequest instead of a StringRequest), e.g.
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("user", "Robby");
jsonObject.put("pass", "zqdqzdqdqzd");
} catch (JSONException e) {
// handle exception (not supposed to happen)
}
StringRequest request = new StringRequest(Request.Method.POST, url, createResponseListener(), createErrorListener()) {
// your code without getParams
#Override
public byte[] getBody() {
try {
return jsonObject.toString.getBytes("utf-8");
} catch (UnsupportedEncodingException uee) {
// not supposed to happen
return null;
}
}
}
Related
I am trying to make Post request from Android App that takes username and password in request body with content-type application/json in headers.
I tried changing content-type and how i send username passoword in body, but still no luck
public class MainActivity extends AppCompatActivity {
private Button Login;
private EditText loginEmail, loginPassword;
String URL = "https://localhost:8080/api/v1/auth";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
loginEmail = (EditText)findViewById(R.id.etUsername);
loginPassword = (EditText)findViewById(R.id.etPassword);
Login = (Button)findViewById(R.id.btnLogin);
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("username", loginEmail.getText().toString());
} catch (JSONException e) {
e.printStackTrace();
}
try {
jsonObject.put("password", loginPassword.getText().toString());
} catch (JSONException e) {
e.printStackTrace();
}
final String requestBody = jsonObject.toString();
Login.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
StringRequest request = new StringRequest(Request.Method.POST, URL, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Toast.makeText(MainActivity.this, response, Toast.LENGTH_LONG).show();
startActivity(new Intent(MainActivity.this, LandingPage.class));
finish();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(MainActivity.this, "Error", Toast.LENGTH_LONG).show();
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);
Toast.makeText(MainActivity.this, res, Toast.LENGTH_LONG).show();
Log.i("MainActivity", res);
//use this json as you want
} catch (UnsupportedEncodingException e1) {
// Couldn't properly decode data to string
e1.printStackTrace();
} catch (JSONException e2) {
// returned data is not JSONObject?
e2.printStackTrace();
}
}
}
})
{
#Override
public String getBodyContentType() {
return "application/json; charset=utf-8";
}
#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
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Content-Type", "application/json");
return params;
}
};
RequestQueue rQueue = Volley.newRequestQueue(MainActivity.this);
rQueue.add(request);
}
});
}
}
Post Request from Postman works perfectly fine but it throws Error 400 with Volley.
Below is the error I get in console
"errorSummary":"Bad request. Accept and/or Content-Type headers likely do not match supported values."
Try using a custom request and extending Request<JSONObject>:
CustomRequest class:
public class CustomRequest extends Request<JSONObject> {
private final Map<String, String> mHeaders;
private final JSONObject mBody;
private final Response.Listener<JSONObject> mResponseListener;
public CustomRequest(int method, String url, Map<String, String> headers, JSONObject body, Response.Listener<JSONObject> responseListener, Response.ErrorListener errorListener) {
super(method, url, errorListener);
this.mHeaders = headers;
this.mBody = body;
this.mResponseListener = responseListener;
}
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
return mHeaders != null ? mHeaders : super.getHeaders();
}
#Override
public String getBodyContentType() {
return "application/json; charset=UTF-8";
}
#Override
public byte[] getBody() throws AuthFailureError {
return mBody != null ? mBody.toString().getBytes(Charset.forName("UTF-8")) : super.getBody();
}
#Override
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
try {
String jsonString = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
return Response.success(new JSONObject(jsonString), HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException | JSONException e) {
return Response.error(new ParseError(e));
}
}
#Override
protected void deliverResponse(JSONObject response) {
mResponseListener.onResponse(response);
}
}
Usage:
String url = "https://localhost:8080/api/v1/auth";
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("username", loginEmail.getText().toString());
jsonObject.put("password", loginPassword.getText().toString());
} catch (JSONException e) {
e.printStackTrace();
}
CustomRequest customRequest = new CustomRequest(Request.Method.POST, url, headers, jsonObject, response -> {
// put your reponse listener code here
}, error -> {
// put your error listener code here
});
RequestQueue queue = Volley.newRequestQueue(context);
queue.add(customRequest);
I am looking to do as per the image says:
Following is the code I am trying to implement from that image:
RequestQueue queue = Volley.newRequestQueue(this);
String url ="https://api.kairos.com/enroll";
StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>() {
#Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
Log.i("Response is: " , response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// mTextView.setText("That didn't work!");
}
})
{
#Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<String, String>();
params.put("app_id", "4985f625");
params.put("app_key", "aa9e5d2ec3b00306b2d9588c3a25d68e");
return params;
}
};
// Add the request to the RequestQueue.
queue.add(stringRequest);
Now I do not get how to add that JSONObject part into my POST Request, and also how to add the Content-Type Header.
I found a similar question here. See the code below. You have to override the getBodyContentType method.
public String getBodyContentType()
{
return "application/json";
}
for content type header you can do the following
StringRequest request = new StringRequest(Request.Method.PUT,
url, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
listener.onResponse(response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(#NonNull VolleyError error) {
if (error.networkResponse != null) {
errorListener.onErrorResponse(error.networkResponse.statusCode, null);
} else {
Log.e(TAG, "An error occurred while trying to verify sms: ", error);
errorListener.onErrorResponse(500, null);
}
}
}) {
#NonNull
#Override
protected Map<String, String> getParams() {
return data;
}
#NonNull
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> headers = new HashMap<>();
headers.put("Content-Type",
"application/x-www-form-urlencoded");
return headers;
}
};
And for send Json object I suggest create Json object like this
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("11", 3);
jsonObject.put("12", 4);
jsonObject.put("13", 5);
} catch (JSONException e) {
e.printStackTrace();
}
Then you can pass this object as string by jsonObject.toString() and pass it in parameters like pass any string like the following
#NonNull
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("json", jsonObject.toString();
return params;
}
I'm trying to use KairosAPI's enroll POST request using Android Volley. However I keep getting Error 1002, image one or more required parameters are missing. I've tried two ways to add the parameters into the body of the JSON, which I've outlined in the code.
This is my code-
public class MainActivity extends AppCompatActivity {
RequestQueue requestQueue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
postRequestToEnrollPersonInGallery();
}
public void postRequestToEnrollPersonInGallery() {
final String appId = "3e12****";
final String appKey = "156e06fd782a3304f085f***********";
String mainUrl = "https://api.kairos.com/";
String enrollRequestUrl = "enroll";
requestQueue = Volley.newRequestQueue(this);
StringRequest stringRequest = new StringRequest(Request.Method.POST, mainUrl + enrollRequestUrl, new Response.Listener<String>() {
#Override
public void onResponse(String response) {
Log.d("Volley", response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("Volley", error.toString());
}
}) {
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<>();
params.put("Content-Type", "application/json");
params.put("app_id", appId);
params.put("app_key", appKey);
return params;
}
#Override
protected Map<String, String> getParams() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("image", "https://s-media-cache-ak0.pinimg.com/originals/c6/c0/04/c6c004ec669d92faa36d8ff447884293.jpg");
params.put("subject_id", "12345");
params.put("gallery_name", "FirstGallery");
/*params.put("image", "\"url\":\"https://s-media-cache-ak0.pinimg.com/originals/c6/c0/04/c6c004ec669d92faa36d8ff447884293.jpg\"");
params.put("subject_id", "\"subject_id\":\"12345\"");
params.put("gallery_name", "\"gallery_name\":\"FirstGallery\""); -- i tried this too*/
return params;
}
};
requestQueue.add(stringRequest);
}
}
You aren't posting JSON.
You can either
1) Learn to use JsonObjectRequest
final JSONObject body = new JSONObject();
body.put(... , ...);
Request request = new JsonObjectRequest(url, body, ...);
2) Actually post a JSON String.
StringRequest request = new StringRequest(...) {
#Override
public byte[] getBody() throws AuthFailureError {
JSONObject params = new JSONObject();
params.put("image", "https://s-media-cache-ak0.pinimg.com/originals/c6/c0/04/c6c004ec669d92faa36d8ff447884293.jpg");
params.put("subject_id", "12345");
params.put("gallery_name", "FirstGallery");
return params.toString().getBytes();
}
#Override
public String getBodyContentType() {
return "application/json";
}
};
I am trying hit an api(written in PHP) and posting params with it.
Here is my code:
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
url, null,
new com.android.volley.Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println("prerna succes volley "+response.toString());
}
}, new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("prerna fail volley "+error.toString());
}
})
{
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> pars = new HashMap<String, String>();
pars.put("Content-Type", "application/x-www-form-urlencoded");
return pars;
}
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("action", "login");
params.put("username", "abc#xyz.com");
params.put("pass", "a");
return params;
}
};
I always get invalid username/password which has been handled in api in case there is invalid username and password.In this case api is not receiving the params.
I tried to do it with retrofit and its working fine with it that means there is no problem at API coding. What am I missing here in case of volley?
Thanks for the support. I am able to solve the problem by changing JsonObjectRequest to StringRequest. i found Volley JsonObjectRequest Post parameters no longer work where I got to know that JsonObjectRequest creates some unexpected problems.
There is my code:
StringRequest jsonObjReq = new StringRequest(Request.Method.POST,
url,
new com.android.volley.Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
JSONObject jsonObject = new JSONObject(response.toString());
String no = jsonObject.getString("$PhoneNo");
} catch (JSONException e) {
}
}
}, new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("prerna fail volley " + error.toString());
}
})
{
#Override
public String getBodyContentType() {
Map<String, String> pars = new HashMap<String, String>();
pars.put("Content-Type", "application/x-www-form-urlencoded");
//return pars;
return "application/x-www-form-urlencoded";
}
#Override
protected Map<String, String> getParams() {
Map<String, String> params = new HashMap<String, String>();
params.put("action", "login");
params.put("username", "abc#xyz.com");
params.put("pass", "a");
return params;
}
};
However I am still trying to figure out why JsonobjectRequest did not work.
As far as I can tell by looking at JsonObjectRequest your 3rd parameter is null, and it indicates the JsonObject request - by the documentation "jsonRequest - A JSONObject to post with the request. Null is allowed and indicates no parameters will be posted along with request."
And after searching again, I saw this thread.
if you are sending your data in raw format you need to try this,first of all make json of your data to be post.
final JSONObject jsonBody = new JSONObject();
jsonBody.put("mobile", phoneNumber);
jsonBody.put("otp", otp.trim());
and you have to override these methods
#Override
public byte[] getBody() throws AuthFailureError {
return jsonBody.toString().getBytes();
}
#Override
public String getBodyContentType() {
return "application/json";
}
if you also have header in your post request you also send that with by following type
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
String auth_token = "bearer" + prefs.getPreferencesString(context, "AuthToken").toString();
params.put("Authorization", auth_token);
return params;
}
Here is the whole code.
final JSONObject jsonBody = new JSONObject();
jsonBody.put("mobile", phoneNumber);
jsonBody.put("otp", otp.trim());
StringRequest sr = new StringRequest(Request.Method.POST, Constraints.Base_URL + "/api/v1/verifyotp", new com.android.volley.Response.Listener<String>() {
#Override
public void onResponse(String response) {
try {
progressDialog.dismiss();
JSONObject jsonObject = new JSONObject(response);
int status = jsonObject.getInt("status");
String token = jsonObject.getString("token");
prefs.setPreferencesString(OtpActivity.this, "AuthToken", token);
if (status == 1) {
startActivity(new Intent(getApplicationContext(), WelcomeScreenActivity.class));
overridePendingTransition(R.anim.right_in, R.anim.left_out);
} else if (status == 0) {
Toast.makeText(OtpActivity.this, "Please Enter Otp!", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
}
}
}, new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Toast.makeText(OtpActivity.this, "Invalid otp please try again!!", Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
}) {
#Override
public byte[] getBody() throws AuthFailureError {
return jsonBody.toString().getBytes();
}
#Override
public String getBodyContentType() {
return "application/json";
}
};
MyApplication.getInstance().addToReqQueue(sr, "jreq");
}
} catch (Exception e) {
}
Try migrating to getHeaders and remove getParams
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("action", "login");
params.put("username", "abc#xyz.com");
params.put("pass", "a");
return pars;
}
Or - Reuse the getParams method
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = getParams();
params.put("Content-Type", "application/x-www-form-urlencoded");
return params;
}
If it is a body request all you need to do is add the extra parameter.
JSONObject body = new JSONObject();
body.put("action", "login");
body.put("username", "abc#xyz.com");
body.put("pass", "a");
JsonObjectRequest jsonObjReq = new JsonObjectRequest(Request.Method.POST,
url, body,
new com.android.volley.Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println("prerna succes volley "+response.toString());
}
},
new com.android.volley.Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("prerna fail volley "+error.toString());
}
});
I use a HttpPost in my code, where I add the entity like this:
String bodyContent = ".......";
HttpPost httpost = new HttpPost(url);
StringEntity se = new StringEntity(bodyContent);
httpost.setEntity(se);
Now I want to change HttpPost in the Volley Request.
How to set setEntity?
I do not understand how I can insert my string bodyContent.
Should I use another method?
boolean contentType = true/false;
//new post request in to volley
StringRequest postRequest = new StringRequest(Request.Method.POST, url,
new Response.Listener<String>()
{
#Override
public void onResponse(String response) {
// response
Log.d("Error.Response", "OK");
}
},
new Response.ErrorListener()
{
#Override
public void onErrorResponse(VolleyError error) {
// error
Log.d("Error.Response", "KO");
}
}
) {
//add body content-type
#Override
public String getBodyContentType() {
if (contentType) {
return "application/json; charset=utf-8";
} else {
return "text/plain; charset=utf-8";
}
}
//add header
#Override
public Map<String, String> getHeaders() throws AuthFailureError
{
Map<String, String> params = new HashMap<String, String>();
params.put("VLHASH", "464646");
return params;
}
#Override
protected Map<String, String> getParams()
{
Map<String, String> params = new HashMap<String, String>();
params.put("name", "Alif");
params.put("domain", "http://itsalif.info");
return params;
}
};
queue.add(postRequest);
You just need to override getBody() as well like you have overridden getBodyContentType in your StringRequest
Sample Code
String body = "test body";
#Override
public byte[] getBody() throws AuthFailureError {
return body.getBytes();
}