【发布时间】:2016-11-10 18:42:27
【问题描述】:
由于 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();
当我使用旧的 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();
}
我一打开连接就收到异常,就好像它连接一样。
调试后,我注意到当我越过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();
}
我正在运行 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() 行时,它就会被评估,从而打开和关闭我的连接。
感谢您的努力,希望这可以为其他人节省一个小时的调试时间。
【问题讨论】:
-
你能发布异常日志吗
-
@VivekMishra 添加了。
-
stackoverflow.com/questions/2793150/…。检查此链接以正确实施开放连接。同样
doInput隐式将请求类型设置为发布,如果您不需要它,您可以删除该行 -
我不使用doInput,我很确定您的意思是
setDoOutput(如果我没记错的话,就是将请求设置为POST)。此外,将我的代码与该问题中接受的答案(POST 请求的代码)进行比较,结果几乎相同(url.openConnection后跟setDoOutput)。我将在运行早期版本 android 的模拟器上进行测试,看看它是否可能是此设备上的错误。 -
当我阅读您的解决方案时,我想,“哇,谁会这样做?”然后我意识到我做了完全相同的事情。你解决了我的问题,而且你并不孤单!