由于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客户端访问它时,工作得很好。我的电脑网络浏览器也是如此。
现在,当我尝试这个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()
,脚本就会执行,日志条目会保存到数据库中(带有一个emptry字符串)。
应该将数据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()
行,就会对其进行评估,从而打开并关闭我的连接。
感谢您的努力,希望这可以节省其他人一小时的调试时间。
答案 0 :(得分: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();
}
}
哪种提供想法可能是一些服务器安全问题。