Android JSON post request with Ruby Web Application connection - java

I'm trying to connect Android json output with Ruby web application.
I'm having difficulty to connect Android json post request with receiving from Ruby app. When Android jsonobject has another jsonobject inside, it is not recognised in the ruby app. Here is my code.
Android Code
JSONObject events_array = new JSONObject();
JSONObject parent=new JSONObject();
for (int i = 0; i < classtimeList.size(); i++) {
events_array.put(classtimeList.get(i).toString(),priorityList.get(i).toString());
}
parent.put("token","token_information");
parent.put("class_type", "something");
parent.put("class_frequency", "5");
parent.put("course_id", "20");
parent.put("events_array", events_array);
String urlParameters = "info="+parent.toString();
Log.i("parameters", urlParameters);
This is a log info for parameters.
info={"token":"token_information","class_type":"something","class_frequency":"5","course_id":"20","events_array":{"3074":"3","3134":"1","3140":"1","3146":"3","3152":"1","3075":"3","3076":"3","3077":"3","3078":"3","3079":"3","3216":"3","3217":"3","3218":"1","3219":"3"}}
I pass this information to Ruby app and I am having difficulty to extract "events_array" information. Below is my Ruby Code.
My full Android code looks like
class apply extends AsyncTask<String, String, String> {
ProgressDialog pd;
private Exception exception;
protected void onPreExecute() {
pd = new ProgressDialog(ClassApply2.this);
pd.setMessage("loading");
pd.show();
}
protected String doInBackground(String... args) {
String token = args[0];
try {
URL url = new URL("https://www.ringleplus.com/api/v1/apply/test");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
JSONObject events_array = new JSONObject();
JSONObject parent=new JSONObject();
for (int i = 0; i < classtimeList.size(); i++) {
events_array.put(classtimeList.get(i).toString(),priorityList.get(i).toString());
}
parent.put("token","token_information");
parent.put("class_type", "something");
parent.put("class_frequency", "5");
parent.put("course_id", "20");
parent.put("events_array", events_array);
connection.setRequestMethod("POST");
connection.setDoOutput(true);
String urlParameters = "info=" + parent.toString();
DataOutputStream dStream = new DataOutputStream(connection.getOutputStream());
dStream.writeBytes(urlParameters);
//dStream.write(data); // <!-- 여기에 url parameter가 들어감
dStream.flush();
dStream.close();
Log.i("parameters", parent.toString());
InputStream in = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuffer buffer = new StringBuffer();
String line = "";
while ((line = reader.readLine()) != null) {
buffer.append(line).append("\n");
}
reader.close();
connection.disconnect();
JSONObject jsonObj = null;
jsonObj = new JSONObject(buffer.toString().trim());
String output = jsonObj.getString("item");
return output;
}
catch(Exception e) {
Log.e("ERROR", e.getMessage(), e);
return null;
}
}
protected void onPostExecute(String response) {
if(response == null) {
response = "THERE WAS AN ERROR";
}
//progressBar.setVisibility(View.GONE);
Log.i("INFO", response);
if (pd != null) {
pd.dismiss();
}
adapter.notifyDataSetChanged();
}
Ruby Code
post :test do
parsed_json = ActiveSupport::JSON.decode(params[:info].to_json)
token = parsed_json["token"]
events_array = parsed_json["events_array"]
output = Array.new
if events_array != nil
events_array.each do |start_time, priority|
if priority.to_i == 1 || priority.to_i == 2
userapply = Userapply.new
userapply.classtime_id = start_time
userapply.user_id = user.id
userapply.priority = priority
userapply.save
output << {:userapply_id => userapply.id, :classtime_id => userapply.classtime_id, :user_id => userapply.user_id, :priority => userapply.priority}
end
end
end
return {status: 'ok', item: events_array}
end
What it supposed to be returned is the information about events_array (i.e. {"3074":"3","3134":"1","3140":"1","3146":"3","3152":"1","3075":"3","3076":"3","3077":"3","3078":"3","3079":"3","3216":"3","3217":"3","3218":"1","3219":"3"} )
but, the Android output log is
I/INFO: events_array
but the token extraction seems working.
token = parsed_json["token"]
If this works, then my gut feeling is parsed_json["events_array"] also should work in some sense. But I'm not stuck here.
If this is resolved, then I want to receive parsed_json["events_array"] as a hash information and want to process the full code and get the "output" instead of events_array to check why this doesn't work.
Please let me know if there is anything I'm missing. I really need some help.
Looking forward to seeing anyone's reply.

I finally figured out where the problem came from. I compared what you send to your server with curl in comment above, and what you try to send from android. And these two things are completly difirent. To send the same from androdid, you should form your urlParameter like that:
JSONObject info = new JSONObject();
info.put("info",parent);
urlParameters = info.toString();
And don't forget to do connection.setRequestProperty("Content-Type", "application/json") after connection.setDoOutput(true).
I tested it outside android, and it returned pretty the same as curl command from your comment above. It should work just fine in android.
PS: Please, be more more attentive next time.

Related

I cant insert data from a java program to laravel app via api

I am new to laravel and I would like to save data to my online server via laravel api from a java program but I am getting errors.
this is my route on api.php:
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::post('hooks','ApiTestController#store');
my ApiTestController: its just handles POST request then saves to the table.
public function store(Request $request)
{
$postdata = json_decode($request->input('post_data'), true);
$datas = $postdata['header'];
$data = $datas[0];
$testH = new TestH();
$testH->test_date = $data['test_date'];
$testH->expiration = $data['test_date'];
$testH->source = $data['source'];
$testH->save();
return $testH;
}
and my java code :
try {
//local development server url
URL url = new URL("http://127.0.0.1:8000/api/hooks");
URLConnection con = url.openConnection();
// activate the output
con.setDoOutput(true);
PrintStream ps = new PrintStream(con.getOutputStream());
//create the JSON String
String json = null;
StringWriter sw = new StringWriter();
JSONWriter wr = new JSONWriter(sw);
try {
wr.object().key("header").array();
wr.object();
wr.key("test_date").value(new Date());
wr.key("source").value("TEST");
wr.key("expiration").value(new Date());
wr.endObject();
wr.endArray().endObject();
json = sw.toString();
System.out.println(json);
} catch (JSONException ex) {
Logger.getLogger(WebConnectSample.class.getName()).log(Level.SEVERE, null, ex);
}
// send to laravel server
ps.print("post_data="+json);
HttpURLConnection httpConn = (HttpURLConnection) con;
InputStream is;
if (httpConn.getResponseCode() >= 419) {
is = httpConn.getErrorStream();
} else {
is = httpConn.getInputStream();
}
// read the server reply
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
// close the print stream
}
ps.close();
} catch (Exception e) {
e.printStackTrace();
}
}
the thing is when I dont save via $testH->save() everything works fine. but if I include it java returns with the following error:
Type error: Argument 1 passed to Illuminate\Routing\Middleware\ThrottleRequests::addHeaders() must be an instance of Symfony\Component\HttpFoundation\Response, string given, called in C:\Users\relixusdev\Documents\WebProjects\tcmsite\vendor\laravel\framework\src\Illuminate\Routing\Middleware\ThrottleRequests.php on line 61
any idea what part causes the error? does it have to do with authentication? i just want to be able to save to the online database via my java program.
Try using Route group with prefix as below
Route::group(['prefix' => 'api'], function() {
Route::post('hooks','ApiTestController#store');
});
if anyone comes here having the same problem, i found out that the problem is that I dont have the created_at and updated_at column at my table. I didn't realized its a requirement for laravel. silly me.

URLConnection and POST method android

I am trying to make a post request using the reference of this documentation. But the problem is that the PHP developer at the other end is not able to receive the value of the parameter hence is not able to send a proper response. Am I missing something out here.
// Edits ;
I am making a HTTP Post request. As you can seen the code below. I am writing the arguments and parameters (location_id=3) to the outputstream. I have also pasted the code for PHP which i have been using. Now the problem is:
The parameter value ( which is 3 ) is not received at the PHP code so I am getting a response which is surrounded by the else block. So I just want to know if there is an error in the android code or the PHP code
#Override
protected Boolean doInBackground(String... params) {
Log.d(Constants.LOG_TAG,Constants.FETCH_ALL_THEMES_ASYNC_TASK);
Log.d(Constants.LOG_TAG," The url to be fetched "+params[0]);
try {
url = new URL(params[0]);
urlConnection = (HttpURLConnection) url.openConnection();
// /* optional request header */
// urlConnection.setRequestProperty("Content-Type", "application/json");
//
// /* optional request header */
// urlConnection.setRequestProperty("Accept", "application/json");
/* for Get request */
urlConnection.setChunkedStreamingMode(0);
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setRequestMethod("POST");
List<BasicNameValuePair> nameValuePairs = new ArrayList<BasicNameValuePair>();
nameValuePairs.add(new BasicNameValuePair("location_id",params[1]));
outputStream = urlConnection.getOutputStream();
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
bufferedWriter.write(writeToOutputStream(nameValuePairs));
int statusCode = urlConnection.getResponseCode();
/* 200 represents HTTP OK */
if (statusCode == 200) {
inputStream = new BufferedInputStream(urlConnection.getInputStream());
response = convertInputStreamToString(inputStream);
Log.d(Constants.LOG_TAG, " The response is " + response);
return true;
}
else {
return false;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(inputStream != null){
inputStream.close();
}
if(outputStream != null){
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return false;
}
// Here is the code for writeToOutputStream
public String writeToOutputStream(List<BasicNameValuePair> keyValuePair)throws UnsupportedEncodingException{
String result="";
boolean firstTime = true;
for(BasicNameValuePair pair : keyValuePair){
if(firstTime){
firstTime = false;
}
else{
result = result.concat("&");
}
result = result + URLEncoder.encode(pair.getKey(), "UTF-8");
result = result + "=";
result = result+ URLEncoder.encode(pair.getValue(),"UTF-8");
}
Log.d(Constants.LOG_TAG," The result is "+result);
return result;
}
// Here is the code for convertInputStream to String
public String convertInputStreamToString(InputStream is) throws IOException {
String line="";
String result="";
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(is));
while((line = bufferedReader.readLine()) != null){
Log.d(Constants.LOG_TAG," The line value is "+line);
result += line;
}
/* Close Stream */
if(null!=inputStream){
inputStream.close();
}
return result;
}
Here is the PHP CODE
<?php
include 'config.php';
header ('Content-Type:application/json');
if(isset($_POST['location_id']))
{
$id=$_POST['location_id'];
$selectThemeQuery = mysql_query("select theme_id from location_theme where location_id='$id'",$conn) or die (mysql_error());
$noRows = mysql_num_rows($selectThemeQuery);
//echo "HI";
if($noRows > 0)
{
$result = array();
while($row = mysql_fetch_assoc($selectThemeQuery))
{
$themeid = $row['theme_id'];
//echo "HI";
$selectNameQuery = mysql_query("select theme_name,theme_image from theme where theme_id='$themeid'",$conn) or die(mysql_error());
$numRows = mysql_num_rows($selectNameQuery);
if($numRows > 0)
{
while($rows = mysql_fetch_assoc($selectNameQuery))
{
$name = $rows['theme_name'];
$image = $rows['theme_image'];
$result[] = array('theme_id'=>$themeid,'theme_name'=>$name, 'theme_image'=>$image);
}
}
}
//echo json_encode($result);
echo json_encode("Hi");
}
else
{
$data2[] = array('Notice'=>false);
echo json_encode($data2);
}
}
else
{
echo "Not Proper Data";
}
?>
Remove:
urlConnection.setChunkedStreamingMode(0);
You use a buffered writer so it can only buffer instead of write.
To force all been written:
bufferedWriter.write(writeToOutputStream(nameValuePairs));
bufferedWriter.flush();
And then ask for a response code. And don't call a response code a status code.
writeToOutputStream() ??? What a terrible name. That function does not write to an output stream. It justs makes a text string.
For Android, I would suggest using a library like Spring-Android.
Spring-Android contains a RestTemplate class, which is a quite effective REST-Client. For example, a simple POST request would be...
myRestTemplate.exchange("http://www.example.net", HttpMethod.POST, new HttpEntity( ...some JSON string ...), String.class );
To create the JSON String, I suggest a library like Jackson, which should work fine on Android, see for example here. Not sure if Jackson integrates as fine in Spring-Android as it does in Spring-Web, but in any case, using it to create the Json Strings manually should work just fine.
for post method
create a string builder first
StringBuilder strbul=new StringBuilder();
then append the data like
strbul.append("name=sangeet&state=kerala");
then write to output stream like
httpurlconnection.getOutput().write(strbul.toString().getBytes("UTF-8"));
php script will recieve that data on
$_POST['name'] and $_POST['state']

String cannot be converted to JSON - Android

I have am trying to convert my response from a POST to JSON. And here is what I am doing:
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuilder response = new StringBuilder();
while((line = rd.readLine()) != null) {
response.append(line).append("\r");
}
rd.close();
Log.i(TAG, response.toString());
JSONObject jsonObject = new JSONObject(response.toString());
But then I get error java.lang.String cannot be converted to JSONObject
But if I make a string, String string; and then I paste the what I logged and set it equal to string, and then try
JSONObject jsonObject = new JSONObject(string);
It works, so why is it working when I paste the logged response, but not when I just use response.toString();?
In the logcat it looks like this {"url": "www.google.com"}. And then when I paste it into string = "{\"url\": \"www.google.com\"}";
Thanks for the help
I met this problem before, try this:
new JSONObject(json.substring(json.indexOf("{"), json.lastIndexOf("}") + 1));
or
if (response != null && response.startsWith("\ufeff")) {
in = in.substring(1);
}
the response from server contains a BOM header
public JSONObject(java.lang.String source)
throws JSONException
Construct a JSONObject from a source JSON text string.
source - A string beginning with { (left brace) and ending with } (right brace).
So while doing response.toString() if the string do not start with { and close with } then it will throw Exception.

HttpURLConection - JSON Response isn't Complete

I am trying to send a request to the Grooveshark API using POST Payload and their requested methods, and I have found a problem. Allow me to show you my code first.
public void getResponse() throws Exception
{
if(service.equals("Grooveshark")) link += getHmacMD5(privateGroovesharkKey, jsonInfo.toString());
if(requestedMethod.equals("GET")) infoURL = new URL(link+arguments);
else infoURL = new URL(link);
HttpURLConnection connection = (HttpURLConnection) infoURL.openConnection();
connection.setRequestMethod(requestedMethod);
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
if(service.equals("Grooveshark"))
{
connection.setRequestProperty("Content-Type","application/json");
OutputStream output = connection.getOutputStream();
output.write(jsonInfo.toString().getBytes());
}
else if(requestedMethod.equals("POST") || requestedMethod.equals("PUT"))
{
OutputStream output = connection.getOutputStream();
output.write(arguments.getBytes());
}
connection.connect();
BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null)
sb.append(line).append('\n');
setJsonResult(sb.toString());
System.out.println(jsonResult);
jsonFinal = new JSONObject(jsonResult);
connection.disconnect();
}
I have got that code up here in my project, and I can successfully send requested to any API Webservice that uses JSON in their responses. Now there's only a problem: In Android, it does not give me the WHOLE answer. I've tried running the code on a separate Java (no Android) project, and I get the following output. Although, if I run it on Android, the Log shows me the following:
{"header":{"hostname":"RHL073"},"result":{"songs":[{"SongID":5443351,"SongName":"??????\u00b7???? (FINAL FANTASY XII????)","ArtistID":713,"ArtistName":"Final Fantasy","AlbumID":898007,"AlbumName":"Final Fantasy XII Original Soundtrack","CoverArtFilename":"","Popularity":1214500005,"IsLowBitrateAvailable":tr
And it stops on that tr. Has it anything to do with the parsing of the file that I actually apply afterwards? I don't think it is, but just in case, here it is [This is how I call the search, JSONHandler being the object that contains the code provided above]:
public void performSearch() throws Exception
{
JSONObject search = new JSONObject();
search.put("method", method);
JSONObject header = new JSONObject();
header.put("wsKey", key);
JSONObject parameters = new JSONObject();
parameters.put("query", getSearchQuery());
parameters.put("country", "Portugal");
parameters.put("limit", limit);
parameters.put("offset", "");
search.put("header", header);
search.put("parameters", parameters);
JSONHandler jsonHandler = new JSONHandler(link, search, "Grooveshark", "POST", "");
JSONObject finalResult = jsonHandler.getJsonFinal();
JSONArray songs = finalResult.getJSONObject("result").getJSONArray("songs");
ArrayList<Result> allResults = new ArrayList<Result>();
for(int i = 0; i < songs.length(); i++)
{
JSONObject inner = (JSONObject) songs.get(i);
String name = inner.getString("SongName");
int ID = inner.getInt("SongID");
String artist = inner.getString("ArtistName");
Result res = new Result(name, artist, ID);
res.setAlbumName(inner.getString("AlbumName"));
boolean low = inner.getBoolean("IsLowBitrateAvailable");
int bit = 0;
if(low) bit = 1;
else bit = 0;
res.setIsLowBitRateAvailable(bit);
}
setResults(allResults);
}
As you can clearly see, I am using the json.org library. I really don't understand what's the problem here. Has anyone got any idea as to why?

Using Java to send data to a form on a website hosted locally

I have a program in Java where I retrieve contents from a database.
Now I have a form in the program, and what I want to do is, on the press of a button, some string (text) content retrieved from the database, should be sent over to a website that I'm hosting locally. The content so sent, should be displayed on the website when refreshed.
Can someone guide me as to how I can achieve this (the sending of data to be displayed over the website)?
Will appreciate a lot, if you could kindly show some sample snippets or give me a reference to some tutorial that can help.
---- Okay so i found a link to a snippet that's supposed to do this, but im unable to understand at this stage as to how exactly this snippet works...can someone please guide me into knowing this better ?
here's the code
try {
// Construct data
String data = URLEncoder.encode("key1", "UTF-8") + "=" + URLEncoder.encode("value1", "UTF-8");
data += "&" + URLEncoder.encode("key2", "UTF-8") + "=" + URLEncoder.encode("value2", "UTF-8");
// Send data
URL url = new URL("http://hostname:80/cgi");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
// Process line...
}
wr.close();
rd.close();
} catch (Exception e) {
}
I'm not sure on how you store and manage any of the records but from Java you can send a HTTP Post to the Url (In your case http://localhost/, probably).
Have a look at http://www.exampledepot.com/egs/java.net/post.html for a snippet on how to do this.
Your Website could then store the received information in a database and display it when you refresh.
Update heres the function
Just a side not this is by no means the best way to do this and I have no idea on how this scales but for simple solutions this has worked for me in the past.
/**
* Posts a Set of forms variables to the Remote HTTP Host
* #param url The URL to post to and read
* #param params The Parameters to post to the remote host
* #return The Content of the remote page and return null if no data was returned
*/
public String post(String url, Map<String, String> params) {
//Check if Valid URL
if(!url.toLowerCase().contains("http://")) return null;
StringBuilder bldr = new StringBuilder();
try {
//Build the post data
StringBuilder post_data = new StringBuilder();
//Build the posting variables from the map given
for (Iterator iter = params.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
String key = (String) entry.getKey();
String value = (String)entry.getValue();
if(key.length() > 0 && value.length() > 0) {
if(post_data.length() > 0) post_data.append("&");
post_data.append(URLEncoder.encode(key, "UTF-8"));
post_data.append("=");
post_data.append(URLEncoder.encode(value, "UTF-8"));
}
}
// Send data
URL remote_url = new URL(url);
URLConnection conn = remote_url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(post_data.toString());
wr.flush();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
while ((inputLine = rd.readLine()) != null) {
bldr.append(inputLine);
}
wr.close();
rd.close();
} catch (Exception e) {
//Handle Error
}
return bldr.length() > 0 ? bldr.toString() : null;
}
You would then use the function as follows:
Map<String, String> params = new HashMap<String, String>();
params.put("var_a", "test");
params.put("var_b", "test");
params.put("var_c", "test");
String reponse = post("http://localhost/", params);
if(reponse == null) { /* error */ }
else {
System.out.println(reponse);
}
The big question is how will you authenticate the "update" from your Java program to your website?
You could easily write a handler on your website, say "/update" which saves the POST body (or value of a request parameter) to a file or other persistent store but how will you be sure that only you can set that value, instead of anybody who discovers it?

Categories