自从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()
这一行时,它被评估并因此打开和关闭我的连接。
感谢您的努力,希望这能为其他人节省一个小时的调试时间。
doInput
隐式地将请求类型设置为POST,您可以删除该行。 - Vivek MishrasetDoOutput
(如果我没记错的话,这个方法是用来设置请求为POST)。另外,将我的代码与那个问题中被接受的答案进行比较(关于POST请求的代码),它们几乎是一样的(先是url.openConnection
,然后是setDoOutput
)。 我打算在一个运行早期版本的安卓模拟器上进行测试,看看是否可能是这个设备的一个bug。 - adnan_e