5

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.

adnan_e
  • 1,764
  • 2
  • 16
  • 25
  • can you post exception log – Vivek Mishra Jul 08 '16 at 08:57
  • @VivekMishra added. – adnan_e Jul 08 '16 at 08:59
  • http://stackoverflow.com/questions/2793150/using-java-net-urlconnection-to-fire-and-handle-http-requests. Check this link for proper implementation of open Connection. Also `doInput` implicitly sets request type to post, if you don't require it you can remove that line – Vivek Mishra Jul 08 '16 at 09:06
  • I don't use doInput, and I'm pretty sure you mean `setDoOutput` (If I recall correctly that's the one that sets the request to POST). Also, comparing my code to the accepted answer in that question (the code for POST requests), it's pretty much the same (`url.openConnection` followed by `setDoOutput`). I'm going to test on an emulator running an earlier version of android to see if it's maybe a bug on this device. – adnan_e Jul 08 '16 at 09:10
  • yes I wanted to say setDoOutput – Vivek Mishra Jul 08 '16 at 09:13
  • You should set the method to POST first. – greenapps Jul 08 '16 at 09:26
  • `writePostParams(params);`. We cannot see what you are doing there. – greenapps Jul 08 '16 at 09:29
  • Thanks for your efforts, see my post edit for the (very stupid) mistake I did. – adnan_e Jul 08 '16 at 09:33
  • 1
    When I read your solution I was like, "Wow who would do that?" and then I realized I had done the exact same thing. You solved my problem, and you are not alone! – Malachi Holden Apr 23 '20 at 23:30

1 Answers1

0

actually your code looks fine, even in documentation they implemented same way you did search "Posting Content" in below link but only missing thing is how you want to send data. they are using chunks urlConnection.setChunkedStreamingMode(0);
https://developer.android.com/reference/java/net/HttpURLConnection.html Let me test their method with my server and check do i get same exaction.

I tested this code its working fine i am not getting that exception

public void testURL() {

        HttpURLConnection urlConnection = null;
        try {
            URL url = new URL("http://www.android.com/");
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.setDoOutput(true);
            urlConnection.setChunkedStreamingMode(0);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            urlConnection.disconnect();
        }
    }

which kind of give idea might it is some server security issue.

  • Interesting, I've also tried to POST my data to `https://posttestserver.com/post.php`, same exception. I could try with chunked streaming mode but I don't see any difference there since my code doesn't even reach that line before the exception gets thrown. – adnan_e Jul 08 '16 at 09:30
  • i will try to run this on different emulator instance lets see. you can send me device specs. –  Jul 08 '16 at 10:04