URL.openConnection() 立即连接

adn*_*n_e 5 android httpurlconnection

由于 Android 从他们的 SDK 中删除了自 6.0 以来的 apache Web 客户端,并且我不希望在我的 apk 中包含该库,因此我正在迁移到 HttpURLConnection 方法。

为了测试,我在我的本地服务器上创建了一个 testPost.php,它除了向我的数据库添加一个日志条目外什么都不做,大致如下:

<?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();
Run Code Online (Sandbox Code Playgroud)

当我使用旧的 Web 客户端访问它时,工作正常。我的 PC 的网络浏览器也是如此。

现在,当我尝试这个 android 代码时:

        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();
        }
Run Code Online (Sandbox Code Playgroud)

我收到异常,就好像我一打开连接就连接了一样。调试后,我注意到只要我跨过url.openConnection(),脚本就会执行并且日志条目被保存到数据库中(带有一个空字符串)。

应该将数据 POST 到我的服务器的完整 android 代码:

        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();
        }
Run Code Online (Sandbox Code Playgroud)

我正在运行 android 6.0.1 的三星 Galaxy S7 上进行测试

补充:也在运行Android 5.0.2的模拟器上试过,结果一样。

异常堆栈跟踪:

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)
Run Code Online (Sandbox Code Playgroud)

解决了
这可能会进入我个人所做的愚蠢事情的名人堂。我的调试器有一个手表设置为connection.getResponseMessage(),一旦我跨过openConnection()线路,它就会得到评估,从而打开和关闭我的连接。

感谢您的努力,希望这可以为其他人节省一个小时的调试时间。

小智 0

实际上,您的代码看起来不错,即使在文档中,它们的实现方式也与您在下面的链接中搜索“发布内容”的方式相同,但唯一缺少的是您想要如何发送数据。他们正在使用块 urlConnection.setChunkedStreamingMode(0);
https://developer.android.com/reference/java/net/HttpURLConnection.html 让我用我的服务器测试他们的方法,并检查我是否得到相同的精确度。

我测试了这段代码,它工作正常,我没有收到该异常

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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

哪种方式可能是某些服务器安全问题。