URL.openConnection()立即连接。

5

自从Android在6.0版本中从SDK中删除了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();

当我使用旧的网络客户端访问时,一切正常。我的电脑浏览器也是如此。

但是,当我尝试使用这段 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();
        }

当我打开连接时,就会出现异常。

经过调试,我注意到只要我跨过url.openConnection(),脚本就会执行并将日志条目保存到数据库中(使用空字符串)。

完整的Android代码,用于向我的服务器POST数据:

        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();
        }

我正在测试一个运行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)
问题已解决
这可能是我做过的愚蠢事情中荣登个人名人堂的一项。 我的调试器设置了一个监视器,用于查看connection.getResponseMessage(),并且当我跨越openConnection()这一行时,它被评估并因此打开和关闭我的连接。

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


你能发布异常日志吗? - Vivek Mishra
@VivekMishra已添加。 - adnan_e
使用Java的URLConnection发出和处理HTTP请求,请查看此链接以获取正确的连接实现。另外,如果您不需要它,doInput 隐式地将请求类型设置为POST,您可以删除该行。 - Vivek Mishra
我不使用doInput,而且我很确定你是指setDoOutput(如果我没记错的话,这个方法是用来设置请求为POST)。另外,将我的代码与那个问题中被接受的答案进行比较(关于POST请求的代码),它们几乎是一样的(先是url.openConnection,然后是setDoOutput)。 我打算在一个运行早期版本的安卓模拟器上进行测试,看看是否可能是这个设备的一个bug。 - adnan_e
1
当我看到你的解决方案时,我就像,“哇,谁会这样做呢?”然后我意识到我也做了同样的事情。你解决了我的问题,你并不孤单! - Malachi Holden
显示剩余4条评论
1个回答

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();
        }
    }

这可能是一些服务器安全问题引起的想法。


有趣的是,我也尝试将我的数据POST到https://posttestserver.com/post.php,但出现了相同的异常。我可以尝试使用分块流模式,但我并没有看到任何区别,因为在抛出异常之前,我的代码甚至没有达到那一行。 - adnan_e
我会尝试在不同的模拟器实例上运行这个程序,看看效果如何。你可以把设备规格发给我。 - user642700

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接