Android Volley POST body request recieved EMPTY at backend - json

i'm using the following code to post a json object to php server :
Map<String, String> paramsMap = new HashMap<String, String>();
paramsMap.put("tag", "jsonParams");
JSONObject jsonObject = new JSONObject(paramsMap);
Log.d("JSON", jsonObject.toString());
JsonObjectRequest jsonRequest = new JsonObjectRequest(Request.Method.POST, url, jsonObject,
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
Log.d("JSON RESPONSE", response.toString());
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.d("JSON ERROR", error.getMessage());
}
});
requestQ.add(jsonRequest);
and using this to receive the object in php:
$body = '';
$handle = fopen('php://input','r');
while(!feof($handle)){
$body .= fread($handle,1024);
}
$logger->log("login request","request body: ".$body);
the problem is that the $body is always empty i used FIDDLER to check my HTTP request and it's there as raw data like this : {"tag":"jsonParams"}
so what am i messing ?
thx in advance.

I know this is an old question, but for future readers...
I have solved the exact same problem by using StringRequest instead of JsonObjectRequest. The constructor differs just very slightly and you can then easily parse string response to JsonObject like this:
JSONObject response = new JSONObject(responseString);

Not sure what was your problem, but for the future googlers:
My problem was that I wasn't reading from php://input
Full code (working):
Java:
JSONObject jsonobj; // declared locally so that it destroys after serving its purpose
jsonobj = new JSONObject();
try {
// adding some keys
jsonobj.put("new key", Math.random());
jsonobj.put("weburl", "hashincludetechnology.com");
// lets add some headers (nested JSON object)
JSONObject header = new JSONObject();
header.put("devicemodel", android.os.Build.MODEL); // Device model
header.put("deviceVersion", android.os.Build.VERSION.RELEASE); // Device OS version
header.put("language", Locale.getDefault().getISO3Language()); // Language
jsonobj.put("header", header);
// Display the contents of the JSON objects
display.setText(jsonobj.toString(2));
} catch (JSONException ex) {
display.setText("Error Occurred while building JSON");
ex.printStackTrace();
}
JsonObjectRequest jsObjRequest = new JsonObjectRequest(Request.Method.POST, URL, jsonobj, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
System.out.println("onResponse()");
try {
result.setText("Response: " + response.toString(2))
System.out.println("Response: " + response.toString(2));
} catch (JSONException e) {
display.setText("Error Occurred while building JSON");
e.printStackTrace();
}
//to make sure it works backwards as well
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
System.out.println("onErrorResponse()");
System.out.println(error.toString());
}
});
System.out.println("After the request is made");
// Add the request to the RequestQueue.
queue.add(jsObjRequest);
Clarification: display and result are two TextView objects I am using to display data on the screen, and queue is Volley's request queue.
PHP:
$inp = json_decode(file_get_contents('php://input')); //$input now contains the jsonobj
echo json_encode(["foo"=>"bar","input"=>$inp]); //to make sure we received the json and to test the response handling
Your Android Monitor should output sth. like :
{
"foo":"bar",
"input":{
"new key":0.8523024722406781,
"weburl":"hashincludetechnology.com",
"header": {
"devicemodel":"Android SDK built for x86",
"deviceVersion":"7.1",
"language":"eng"
}
}
}

Related

Consume jira rest with java

i'm using java and i want to consume the json in this url : http://jiraserver/rest/dev-status/latest/issue/detail?issueId=13879&applicationType=stash&dataType=repository
on the browser this url works perfectly and i get all json data needed but in my java program i get
java.io.IOException: Server returned HTTP response code: 400 for URL:
http://jiraserver/rest/dev-status/latest/issue/detail?issueId=13879&applicationType=stash&dataType=repository
public static void main(String[] args) {
System.out
.println(jsonGetRequest("http://jiraserver/rest/dev-status/latest/issue/detail?issueId=13879&applicationType=stash&dataType=repository
"));
}
private static String streamToString(InputStream inputStream) {
String text = new Scanner(inputStream, "UTF-8").useDelimiter("\\Z").next();
return text;
}
public static String jsonGetRequest(String urlQueryString) {
String json = null;
try {
URL url = new URL(urlQueryString);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setInstanceFollowRedirects(false);
connection.setRequestMethod("GET");
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("charset", "utf-8");
connection.connect();
InputStream inStream = connection.getInputStream();
json = streamToString(inStream); // input stream to string
} catch (IOException ex) {
ex.printStackTrace();
}
return json;
}
am i missing something ? if there's any simple implementation to consume that url feel free

How do I send a HTTP request using OAUTH2 in Android?

I am trying to retrieve the data from my account by connecting to the Fitbit API. I have my app returning the Access Token I need to make the HTTP Request that returns the JSON but anything that I try, it returns an error. I have two Activities - MainActivity.java and TestActivity.java
In MainActivity.java I am simply opening a Chrome Custom Tab to direct the user to the Fitbit Authentication(Login) page. Once the user enters their details they are redirected back to the TestActivity.java as per the Fitbit API documentation. I am then printing the Acess Token which proves to me that it is connecting to the API.
What I need to do it make an HTTP request to returns the sleep data in JSON format. I know how to do it in Java but I am unsure how to do it in Android using the AsyncTask way. Any help is appreciated!
public class TestActivity extends AppCompatActivity {
String string;
String token;
#Override
protected void onNewIntent(Intent intent) {
string = intent.getDataString();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
onNewIntent(getIntent());
//Toast.makeText(TestActivity.this, string , Toast.LENGTH_LONG).show();
Log.e("TAG", string);
Log.e("TAG", string.substring(string.indexOf("&access_token")+14));
token = string.substring(string.indexOf("&access_token")+14);
Context context = getApplicationContext();
Toast toast = Toast.makeText(context,"Access Token: "+ token,Toast.LENGTH_LONG );
Log.i("TAG", "Access Token: "+ token);
new JSONTask().execute("https://api.fitbit.com/1.2/user/-/sleep/date/2018-01-30.json");
}
public class JSONTask extends AsyncTask<String,String,String>
{
#Override
protected String doInBackground(String... params) {
HttpURLConnection connection = null;
BufferedReader reader = null;
try
{
URL url = new URL(params[0]);
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", "Bearer " + token);
connection = (HttpURLConnection) url.openConnection();
connection.connect();
InputStream stream = connection.getInputStream();
reader = new BufferedReader(new InputStreamReader(stream));
StringBuffer buffer = new StringBuffer();
String line = "";
while((line = reader.readLine()) !=null)
{
buffer.append(line);
}
return buffer.toString();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s)
{
super.onPostExecute(s);
Log.i("TAG", s);
}
}
I ended up having a breakthrough with this question. I figured out that I was extracting the Access Token incorrectly. So, instead of doing the following:
token = string.substring(string.indexOf("&access_token")+14);
I instead had to use this:
token = string.substring(string.indexOf("&access_token")+36,308);
The App was then able to make the necessary HTTP request to the Fitbit API which returned the JSON data that I needed.
One order of codes should be changed for preventing FC.
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setRequestProperty("Authorization", "Bearer " + token);

AngularJS post to Jersey generates com.sun.jersey.server.wadl.generators.WadlGeneratorJAXBGrammarGenerator$8 resolve SEVERE: null

I have a jersey server. When I attempt to handle a POST from AngularJS (1.2.16), it is generating an error (below). When I use a java jersey client to post the message, the jersey server handles it fine.
SEVERE: null
java.lang.IllegalAccessException: Class com.sun.jersey.server.wadl.generators.WadlGeneratorJAXBGrammarGenerator$8 can not access a member of class javax.ws.rs.core.Response with modifiers "protected"
at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:101)
at java.lang.Class.newInstance(Class.java:427)
this is the jersey post server:
#POST
#Consumes(MediaType.APPLICATION_JSON)
#Produces(MediaType.APPLICATION_JSON)
#Path("/post")
public Response verifyAccount( Owner owner ,
#Context HttpServletRequest req)
{
LOGGER.debug("verify account " +owner.toString() );
HashMap<String, Object> results = new HashMap<String, Object>();
boolean verified = AccountManagement.verifyAccount(owner.getEmail(),
owner.getPwd());
if (verified) {
results.put("status", "OK");
} else {
results.put("status", "Fail");
}
return Response.status(200).entity(results)
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE")
.build();
}
This is the jersey java client:
public class JsonClient {
public static void main(String[] args) {
try {
Client client = Client.create();
WebResource webResource = client
.resource("http://myserver.com:8080/restws/accountcheck/post");
String input = "{\"email\":\"fubar#gmail.com\",\"pwd\":\"hello\"}";
ClientResponse response = webResource.type("application/json")
.post(ClientResponse.class, input);
int code = response.getStatus();
if (code != 200) {
throw new RuntimeException("Failed : HTTP error code : "
+ response.getStatus());
}
System.out.println("Output from Server .... \n");
String output = response.getEntity(String.class);
System.out.println(output);
} catch (Exception e) {
System.out.println("exception caught.");
e.printStackTrace();
}
}
}
This is the AngularJS code to post:
$scope.ownerLoginAction = function() {
var dataObject = {
"email": $scope.myId,
"pwd": $scope.mypassword
};
var request = $http({
method: "post",
url: hostName+'/restws/accountcheck/post',
params: {
action:"verify"
},
data: dataObject
});
request.then (function(response) {
console.log(response.data);
},function(errResponse) {
console.error('Error');
} )
}
Anybody know why I cannot seem to post either with JSON from AngularJS? Is the server not set up right? Or the angularJS client is not right?
When i put a TCPMON in between, I noticed that the angularJS attempt sent an OPTION. Is that a clue that I dont understand?

Post string request volley?

I want to POST the following string to a server and receive a JSONObject via android volley! The documentation says the request to the server should be in the format given below, with Content-Type as "application/x-www-form-urlencoded". How do I make this request with volley?
{
Username=usr&Password=passwd&grant_type=passwd
}
Thanks in advance!
First you should Override your getbody() and in that function encode your parameteres... for example:
#Override
public byte[] getBody() {
Map<String, String> params = new HashMap<String, String>();
params.put("password", "yourpassword");
if (params != null && params.size() > 0) {
return encodeParameters(params, getParamsEncoding());
}
return null;
}
protected byte[] encodeParameters(Map<String, String> params, String paramsEncoding) {
StringBuilder encodedParams = new StringBuilder();
try {
for (Map.Entry<String, String> entry : params.entrySet()) {
encodedParams.append(URLEncoder.encode(entry.getKey(), paramsEncoding));
encodedParams.append('=');
encodedParams.append(URLEncoder.encode(entry.getValue(), paramsEncoding));
encodedParams.append('&');
}
return encodedParams.toString().getBytes(paramsEncoding);
} catch (UnsupportedEncodingException uee) {
throw new RuntimeException("Encoding not supported: " + paramsEncoding, uee);
}
}
this the way to encode your parameters.... volley actually has implemented the following function, and it works, for me it works... hope this help you.
So your question is confusing. POST body parameters aren't encoded inside a JSON body.
I haven't tested it but if you understand HTTP you should understand the rest from here.
final Map<String, String> postBody = new HashMap<String, String>();
postBody.put("Username", "usr");
postBody.put("Password", "passwd");
postBody.put("grant_type", "passwd");
final Listener<JSONObject> responseListener = ...;
Request request = new Request<JSONObject>(Method.POST, "http://example.com", errorListener) {
void deliverResponse(JSONObject obj) {
responseListener.onResponse(obj);
}
protected Map<String, String> getPostParams() throws AuthFailureError {
return postBody;
}
protected Response<T> parseNetworkResponse(NetworkResponse response) {
if (response.status == 200) {
JSONObject responseBody = new JSONObject(new String(response.data));
return Response.success(body, getCacheEntry());
} else {
return new Response<JSONObject>(new VolleyError(response);
}
}
};
requestQueue.add(request);

how to handle http 400 and 401 error while using webclient to download JSON

I am using an api that returns an error 400 if URL is invalid and error 401 if daily qouta is exhausted by 50%. it also returns the json but am not able to download this json as an exception occurs if these error occurs. the api am using is
http://www.sharedcount.com/documentation.php
the code am using write now is...
private void _download_serialized_json_data(Uri Url)
{
var webClient = new WebClient();
var json_data = string.Empty;
// attempt to download JSON data as a string
try
{
webClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(webClient_DownloadStringCompleted);
webClient.DownloadStringAsync(Url);
}
catch (Exception) { }
}
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
String Json = null;
try
{
Json = e.Result;
}
catch (Exception ex)
{
}
if(Json!=null)
{
data=JsonConvert.DeserializeObject<RootObject>(Json);
result.Text = "facebook : "+data.Facebook.like_count+"\nGooglePlus : "+data.GooglePlusOne;
}
else
{
result.Text = "Invald URL \nor you exceeded your daily quota of 100,000 queries by 50%.";
}
}
currently am showing both errors if exception occurs. but i want to download the json and display that. how should i do that
To get the response content, you will need to use System.Net.Http.HttpClient instead. Install it from here: Microsoft HTTP Client Libraries
Then try this:
private async void Foo2()
{
Uri uri = new Uri("http://localhost/fooooo");
HttpClient httpClient = new HttpClient();
HttpResponseMessage response = await httpClient.GetAsync(uri);
HttpStatusCode statusCode = response.StatusCode; // E.g.: 404
string reason = response.ReasonPhrase; // E.g.: Not Found
string jsonString = await response.Content.ReadAsStringAsync(); // The response content.
}
You can try something like this,
void webClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
String Json = null;
if(e.Error != null)
{
//Some error occured, show the error message
var ErrorMsg = e.Error.Message;
}
else
{
//Got some response .. rest of your code
Json = e.Result;
}
}
I ran into this same issue using WebClient, I saw the error response stream being captured in Fiddler, but my .NET code was catching the exception and did not appear to be capturing the response stream.
You can read the Response stream from the WebException object to get the response data stream out.
using (System.Net.WebClient client = new System.Net.WebClient())
{
string response = "";
try
{
response = client.UploadString(someURL, "user=billy&pass=12345");
}
catch(WebException ex)
{
using (System.IO.StreamReader sr = new System.IO.StreamReader(ex.Response.GetResponseStream()))
{
string exResponse = sr.ReadToEnd();
Console.WriteLine(exResponse);
}
}
}