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.