Since Android removed the apache web client since 6.0 from their SDK and I don't wish to include the library in my apk, I'm migrating to the HttpURLConnection method.
To test things out, I created a testPost.php on my local server which does nothing but add a log entry to my database, roughly like this:
<?php
require_once(__DIR__ . '/db_interface.php');
$conn = connectToDatabase();
$stmt = $conn->prepare('insert into logs(data) values (?)');
$stmt->bind_param(1, $_POST['data']);
$stmt->execute();
$stmt->close();
And when I access that with my old web client, works just fine. Same goes for my PC's web browser.
Now, when I try this android code:
HttpURLConnection connection = null;
try {
URL url = new URL("http://192.168.2.221/testPost.php");
connection = (HttpURLConnection) url.openConnection();
//As soon as the debugger steps over the above line, the
//PHP script executes.
//Line below throws IllegalStateException: Already Connected
connection.setDoOutput(true);
...
} finally {
if ( connection != null ) connection.disconnect();
}
I get the exception as if it connects as soon as I open the connection.
After debugging, I noticed that as soon as I step overurl.openConnection(), the script executes and the log entry is saved into the database (with an emptry string).
The full android code which is supposed to POST data to my server:
HttpURLConnection connection = null;
try {
URL url = new URL("http://192.168.2.221/testPost.php");
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true); //throws IllegalStateException: Already Connected
if ( timeout > 0 ) {
connection.setReadTimeout(timeout * 1000);
connection.setConnectTimeout(timeout * 1000);
}
String postString = writePostParams(params);
byte[] postData = postString.getBytes("UTF-8");
connection.setFixedLengthStreamingMode(postData.length);
OutputStream out = new BufferedOutputStream(connection.getOutputStream());
out.write(postData);
out.flush();
out.close();
InputStream in = new BufferedInputStream(connection.getInputStream());
String response = Util.readInputStream(in);
} catch ( Exception ex ) {
Debug.log(ex);
} finally {
if ( connection != null ) connection.disconnect();
}
I'm testing on a Samsung Galaxy S7 running android 6.0.1
Add: Also tried on an emulator running Android 5.0.2, same results.
Exception stacktrace:
07-08 10:39:30.141 23498-23875/? W/System.err: java.lang.IllegalStateException: Already connected
07-08 10:39:30.141 23498-23875/? W/System.err: at java.net.URLConnection.checkNotConnected(URLConnection.java:463)
07-08 10:39:30.141 23498-23875/? W/System.err: at java.net.URLConnection.setDoOutput(URLConnection.java:877)
07-08 10:39:30.141 23498-23875/? W/System.err: at com.package.from.my.app.executeURL(Server.java:1195) (the line where setDoOutput() is)
SOLVED
This might go to my personal hall of fame of stupid things I did.
My debugger had a watch set to connection.getResponseMessage(), and as soon as I stepped over the openConnection() line, it got evaluated and thus opened and closed my connection.
Thanks for your effort, hope this saves someone else an hour of debugging.