Sending POST JSON data using HttpURLConnection and AsyncTask - java

I'm trying to send some JSON data (if its a problem it may be a normal string) but it's not working at all.
When I add getResponseCode it sends POST with empty body to the server but the headers are set (Content-Type - application/json). I tried on many different ways but there is always empty body. Can someone look at it? I feel like I am missing something important...
//when button is tapped:
final String url = "http://postcatcher.in/catchers/";
new AsyncHttpTask().execute(url);
public class AsyncHttpTask extends AsyncTask<String, Void, Integer> {
#Override
protected Integer doInBackground(String... strings) {
try {
URL url = new URL(strings[0]);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type","application/json");
// conn.getResponseCode
JSONObject jsonParam = new JSONObject();
jsonParam.put("name", "Andrew");
jsonParam.put("code", "5412274");
OutputStreamWriter os = new OutputStreamWriter(conn.getOutputStream());
os.write(jsonParam.toString());
os.flush();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
The thing is that when I am using that conn.getResponse Code I'm sure that there is connection with server but the body is empty.
When i delete it, the POST message are not sending at all (seems that it is not working)

On that place you have not send anything yet so you cannot expect a response. You will have an IOException for that then. Log it and look in the logcat. If you want to know the response you should put it after you have send all. So after os.flush(). But you are not reading the response. The webserver will send something back isn't it? You are not reading that from conn.getInputStream(). Read it otherwise you will never know what the catcher answers.

Related

How to properly post url in android with java using HttpURLConnection

I try to use HttpURLConnection to send a post request to my local (xampp) server with an url like this http://xxx.xxx.0.3/Company/index.php/booking/c200/p-205/2025-02-09 8:2 , the server php file take param in url and send data to mysql database .
The url works fine on postman agent , and even another get method request works smooth in the android application .
Yet when i try the post method with following code :
public void postOrder() {
TextView tv = findViewById(R.id.tv1);
Thread t = new Thread( new Runnable() {
#Override
public void run() {
HttpURLConnection conn = null;
try {
String link = "http://xxx.xxx.0.3/Company/index.php/booking/c200/p-205/2025-02-09 8:2";
URL url = new URL(link);
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setReadTimeout(10000 /*ms*/);
conn.setConnectTimeout(15000 /*ms*/);
conn.connect();
}
catch (IOException e) {
Log.d("HTTP error: ", e.toString());
}
finally {
conn.disconnect();
}
}
} );
t.start();
}
It never sent the url and thus no data is stored to database .
And with 6 hours of trial and error , google and searching , i added this line of code :
InputStream is = conn.getInputStream();
And it finally works .
Please answer me why it only works after adding this line of code , what does it do ? I thought the url is triggered right after conn.connect();
Calling connect() only connects, but it doesn't send anything yet. Call getResponseCode() to force the request to be sent. That method is safer than getInputStream() which will throw an exception if the response is not a 2xx (in which case you'd need getErrorStream()).

How to send many/multiple post requests of JSONObjects on Android?

There's a lot of questions on StackOverflow for sending a single POST request on Android, but none of them cover cases where you're receiving lots of data from a sensor connected to your phone and need to Post Request that data as you receive it.
I'm receiving data from a sensor connected to my Android, and need to to send it to a Flask server hosted on Heroku.
public void sendToFlask(JSONObject jsonParam) {
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
try {
URL url = new URL("URLHERE");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
conn.setRequestProperty("Accept","application/json");
conn.setDoOutput(true);
conn.setDoInput(true);
Log.i("JSON", jsonParam.toString());
DataOutputStream os = new DataOutputStream(conn.getOutputStream());
//os.writeBytes(URLEncoder.encode(jsonParam.toString(), "UTF-8"));
os.writeBytes(jsonParam.toString());
os.flush();
os.close();
Log.i("STATUS", String.valueOf(conn.getResponseCode()));
Log.i("MSG" , conn.getResponseMessage());
conn.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
});
This code unfortunately errors out for creating too many files
I understand that the solution here may be to use a global HttpURLConnection but unfortunately that also gives me the error of java.net.ProtocolException: cannot write request body after response has been read This happens after I move the conn and url variables to global scope and set them in onCreate

How to send via post in java an information to a php page?

I am having trouble sending through a java application the data to a page in php. Basically, I have a page in php that receives the data through the POST method and created a class in java that sends this data via post. The problem is that in java I do not insert the identifier that is requested in the php page. As you can see, I get the value on the page in php by the filter_input (INPUT_POST, "user") code snippet, but in the java application I do not enter this "user" identifier in the information I want to send. So, there's no way the php page "picks up" the value that the java application is sending. Anyone have any ideas how to solve this problem? Thank you very much in advance!
Page PHP:
<?php
require_once './vendor/autoload.php';
$controller = new App\CWS\Controller();
if($_SERVER['REQUEST_METHOD'] == "POST"){
$controller->registerUser(filter_input(INPUT_POST, "user"));
}
?>
Class responsible for connecting and sending data in the Java application:
public class WebClient {
public String post(String json) {
try {
URL url = new URL("http://localhost//CWS//cadastrar_usuario.php");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-type", "application/json");
connection.setRequestProperty("Accept", "application/json");
connection.setDoOutput(true);
PrintStream output = new PrintStream(connection.getOutputStream());
output.println(json);
connection.connect();
Scanner scanner = new Scanner(connection.getInputStream());
String resposta = scanner.next();
return resposta;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
PrintStream output = new PrintStream(connection.getOutputStream());
output.println(json);
With this you are sending the data as JSON encoded text to the server.
Whatever is in the JSON string at this point will be sent.
If you have not put the data for "user" in the JSON, you have to put it before sending it.

GCM Push Notifications are not delivered to devices

We (Panos and Rainer - see the comments down) have a server and several Android devices.
We want to send push notifications from our server via GCM to the Android devices.
Now we make a post request to the GCM server. The GCM server response is that all is fine (success==1 and even the message-id)!
BUT the push notification(s) are never delivered to the devices.
If we use the same data and the Chrome addon Postman - the notifications are delivered immediately.
We tried all lot of different solutions. We get always the feedback of the GCM server that all is ok - but the push notifications aren't send.
We also tried this one:
https://github.com/googlesamples/google-services/blob/master/android/gcm/gcmsender/src/main/java/gcm/play/android/samples/com/gcmsender/GcmSender.java
You might also post the URL you use. There is a new GCM enpoint which looks like the following:
https://gcm-http.googleapis.com/gcm/send
I am not yet sure what's causing the issues on your side. But the following is tested and working:
public class Main {
public static void main(String[] args) {
// write your code here
try {
String url = "https://gcm-http.googleapis.com/gcm/send";
URL obj = new URL(url);
HttpsURLConnectionImpl conn = (HttpsURLConnectionImpl) obj.openConnection();
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty ("Authorization", "key=***");
String title = "Short title";
String body = "A body :D";
String token = "****";
String data = "{ \"notification\": { \"title\": \"" + title +"\", \"body\": \"" + body + "\" }, \"to\" : \"" + token + "\", \"priority\" : \"high\" }";
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(data);
out.close();
String text = getText(new InputStreamReader(conn.getInputStream()));
System.out.println(text);
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getText(InputStreamReader in) throws IOException {
StringBuilder sb=new StringBuilder();
BufferedReader br = new BufferedReader(in);
String read;
while((read=br.readLine()) != null) {
sb.append(read);
}
br.close();
return sb.toString();
}
}
This is the data used for the Postman request which is working without any problem.
Rainer already mentioned that we tried several implementations on the Java side and it seems that we are always able to communicate with the service and receive a response which seems to look correct so far:
{
"multicast_id":7456542468425129822,
"success":1,
"failure":0,
"canonical_ids":0,
"results":
[{
"message_id":"0:1457548597263237%39c590d7f9fd7ecd"
}]
}
Not sure if I'm on the right track but do you mean downstream HTTP messages (plain text)?
Tried to send the following JSON to the service (from Postman) which results again in a positive response but this time the notification did not reach the device (just to make that clear, at the moment there is no app on the device listening actively for incoming notifications -> first of all we just want to ensure that they generally arrive on the device):
{
"data":
{
"score": "5x1",
"time": "15:10"
},
"to" : "SECRET-DEVICE-TOKEN"
}
Thanks to all of you trying to help here but to be honest, this issue is really frustrating. Communicating with an interface\service which seems not to be able to return a useful response in case the request contains maybe evil stuff which will finally prevent GCM from sending the push notification to the device, feels like a pain in the ass. If Postman would also fail I would say ok, you can not be so stupid :-)
Here are some quick'n dirty implementations we have already used.
Example
try
{
URL url = new URL(apiUrl);
HttpsURLConnection conn = (HttpsURLConnection);//also tried HttpURLConnection
url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestProperty("Authorization", "key="+apiKey);
conn.setDoOutput(true);
String json = "{\"priority\":\"high\",\"notification\":{\"title\":\"Some title\",\"text\":\"Some text\"},\"to\":\""+deviceToken+"\"}";
OutputStream os = conn.getOutputStream();
os.write(json.getBytes());
os.flush();
}
catch(Exception exc)
{
System.out.println("Error while trying to send push notification: "+exc);
}
Example
HttpClient httpClient = HttpClientBuilder.create().build();
try
{
HttpPost request = new HttpPost(apiUrl);
StringEntity params =new StringEntity("{\"priority\":\"high\",\"notification\":{\title\":\"Some title\",\"text\":\"Some text\"},\"to\":\""+deviceToken+"\"}");
request.addHeader("Content-Type", "application/json");
request.addHeader("Authorization", "key="+apiKey);
request.setEntity(params);
HttpResponse response = httpClient.execute(request);
// check response
System.out.println(response.getStatusLine().toString());
}catch (Exception exc) {
System.out.println("Error while trying to send push notification: "+exc);
} finally {
httpClient.getConnectionManager().shutdown(); //Deprecated
}
Example
try
{
String charset = "UTF-8";
URLConnection connection = new URL(apiUrl).openConnection();
connection.setDoOutput(true);
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-Type", "application/json;charset=" + charset);
connection.setRequestProperty("Authorization", "key="+apiKey);
String param = "{\"priority\":\"high\",\"notification\":{\"title\":\"Some title\",\"text\":\"Some text\"},\"to\":\""+deviceToken+"\"}";
try (OutputStream output = connection.getOutputStream())
{
output.write(param.getBytes(charset));
}
InputStream response = connection.getInputStream();
}
catch(Exception exc)
{
System.out.println("Error while trying to send push notification: "+exc);
}
Example
try
{
// prepare JSON
JSONObject jGcmData = new JSONObject();
JSONObject jData = new JSONObject();
jData.put("message", "{ \"data\": {\"score\": \"5x1\",\"time\": \"15:10\"},\"to\" : \""+deviceToken+"\"}");
jGcmData.put("to", deviceToken);
jGcmData.put("data", jData);
// Create connection to send GCM Message request.
URL url = new URL("https://android.googleapis.com/gcm/send");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestProperty("Authorization", "key=" + apiKey);
conn.setRequestProperty("Content-Type", "application/json");
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// Send GCM message content.
OutputStream outputStream = conn.getOutputStream();
outputStream.write(jGcmData.toString().getBytes());
// Read GCM response.
InputStream inputStream = conn.getInputStream();
String resp = IOUtils.toString(inputStream);
System.out.println(resp);
} catch (IOException e) {
System.out.println("Unable to send GCM message. "+e);
}
Mike, with your example it's working also on our side. After comparing your implementation with the on eon our side, the only real difference I found is the used URL!!
Somehow the URL used in our Java implementation was https://android.googleapis.com/gcm/send
Seems that https://gcm-http.googleapis.com/gcm/send is the right one which by the way was also used for our Postman tests.
But why on hell is the URL from our failed tests still somehowe valid and returns a response!?
Setting the priority to high in the json resolved the issue for me.
'registration_ids' => $id,
'priority' => 'high',
'data' => $load
For our case, the clients Android devices had intermittent internet connection issue, that is, network dropouts thus causing notification delivery failed. We resolved the reliability issue with the following JAVA GCM code:
gcmPayload.setTime_to_live(messageExpiryTime); //in seconds. Set notification message expiry to give user time to receive it in case they have intermittent internet connection, or phone was off
gcmPayload.setPriority("high");
and APNS code:
ApnsService apnsService = APNS.newService().withCert(certificateStream, configurations.getApnPassword()).withProductionDestination().build();
PayloadBuilder payloadBuilder = APNS.newPayload();
...
payloadBuilder.instantDeliveryOrSilentNotification(); //same as content-available=true
String payload = payloadBuilder.build();
Integer now = (int)(new Date().getTime()/1000);
//use EnhancedApnsNotification to set message expiry time
for(String deviceToken : deviceTokens) {
EnhancedApnsNotification notification = new EnhancedApnsNotification(EnhancedApnsNotification.INCREMENT_ID() /* Next ID */,
now + messageExpiryTime /* Expiry time in seconds */,
deviceToken /* Device Token */,
payload);
apnsService.push(notification);
}
Also, remember to consider time zone if your backend server time is different to the client mobile app time.

The correct way to PUT a JSON object to a RESTful server

I am having trouble correctly formatting my PUT request to get my server to recognise my client application's PUT command.
Here is my section of code that puts a JSON string to the server.
try {
URI uri = new URI("the server address goes here");
URL url = uri.toURL();
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(gson.toJson(newClient));
out.close();
} catch (Exception e) {
Logger.getLogger(CATHomeMain.class.getName()).log(Level.SEVERE, null, e);
}
and here is the code that is supposed to catch the PUT command
#PUT
#Consumes("text/plain")
public void postAddClient(String content, #PathParam("var1") String var1, #PathParam("var2") String var2) {
What am I doing wrong?
You also need to tell the client side that it is doing a PUT of JSON. Otherwise it will try to POST something of unknown type (the detailed server logs might record it with the failure) which isn't at all what you want. (Exception handling omitted.)
URI uri = new URI("the server address goes here");
HttpURLConnection conn = (HttpURLConnection) uri.toURL().openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("PUT");
conn.addRequestProperty("Content-Type", "application/json");
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(gson.toJson(newClient));
out.close();
// Check here that you succeeded!
On the server side, you want that to declare that it #Consumes("application/json") of course, and you probably want the method to either return a representation of the result or redirect to it (see this SO question for a discussion of the issues) so the result of your method should not be void, but rather either a value type or a JAX-RS Response (which is how to do the redirect).
Probably the MIME type. Try "application/json".

Categories