java Android:HttpURLConnection 无法正常工作
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12693138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android: HttpURLConnection not working properly
提问by giorgiline
I'm trying to get the cookies from a website after sending user credentials through a POST Request an it seems that it doesn't work in android this way. ?Am I doing something bad?. Please help. I've searched here in different posts but there's no useful answer.
在通过 POST 请求发送用户凭据后,我试图从网站获取 cookie,但这种方式在 android 中似乎不起作用。?我在做坏事吗?。请帮忙。我在不同的帖子中在这里搜索过,但没有有用的答案。
It's curious that this run in a desktop Java implementation it works perfect but it crashes in Android platform. And it is exactly the same code, specifically when calling HttpURLConnection.getHeaderFields(), it also happens with other member methods. It's a simple code and I don't know why the hell isn't working.
奇怪的是,这在桌面 Java 实现中运行它运行完美,但它在 Android 平台上崩溃。它是完全相同的代码,特别是在调用 HttpURLConnection.getHeaderFields() 时,其他成员方法也会发生这种情况。这是一个简单的代码,我不知道为什么它不起作用。
DESKTOP CODE: This goes just in the main()
桌面代码:这只是在 main()
HttpURLConnection connection = null;
OutputStream out = null;
try {
URL url = new URL("http://www.XXXXXXXX.php");
String charset = "UTF-8";
String postback = "1";
String user = "XXXXXXXXX";
String password = "XXXXXXXX";
String rememberme = "on";
String query = String.format("postback=%s&user=%s&password=%s&rememberme=%s"
, URLEncoder.encode(postback, charset)
, URLEncoder.encode(user,charset)
, URLEncoder.encode(password, charset)
, URLEncoder.encode(rememberme, charset));
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Accept-Charset", charset);
connection.setDoOutput(true);
connection.setFixedLengthStreamingMode(query.length());
out = connection.getOutputStream ();
out.write(query.getBytes(charset));
if (connection.getHeaderFields() == null){
System.out.println("Header null");
}else{
for (String cookie: connection.getHeaderFields().get("Set-Cookie")){
System.out.println(cookie.split(";", 2)[0]);
}
}
} catch (IOException e){
e.printStackTrace();
} finally {
try { out.close();} catch (IOException e) { e.printStackTrace();}
connection.disconnect();
}
So the output is:
所以输出是:
login_key=20ad8177db4eca3f057c14a64bafc2c9
FASID=cabf20cc471fcacacdc7dc7e83768880
track=30c8183e4ebbe8b3a57b583166326c77
client-data=%7B%22ism%22%3Afalse%2C%22showm%22%3Afalse%2C%22ts%22%3A1349189669%7D
ANDROID CODE: This goes inside doInBackground AsyncTask body
ANDROID 代码:这在 doInBackground AsyncTask 主体中
HttpURLConnection connection = null;
OutputStream out = null;
try {
URL url = new URL("http://www.XXXXXXXXXXXXXX.php");
String charset = "UTF-8";
String postback = "1";
String user = "XXXXXXXXX";
String password = "XXXXXXXX";
String rememberme = "on";
String query = String.format("postback=%s&user=%s&password=%s&rememberme=%s"
, URLEncoder.encode(postback, charset)
, URLEncoder.encode(user,charset)
, URLEncoder.encode(password, charset)
, URLEncoder.encode(rememberme, charset));
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Accept-Charset", charset);
connection.setDoOutput(true);
connection.setFixedLengthStreamingMode(query.length());
out = connection.getOutputStream ();
out.write(query.getBytes(charset));
if (connection.getHeaderFields() == null){
Log.v(TAG, "Header null");
}else{
for (String cookie: connection.getHeaderFields().get("Set-Cookie")){
Log.v(TAG, cookie.split(";", 2)[0]);
}
}
} catch (IOException e){
e.printStackTrace();
} finally {
try { out.close();} catch (IOException e) { e.printStackTrace();}
connection.disconnect();
}
And here there is no output, it seems that connection.getHeaderFields() doesn't return result. It takes al least 30 seconds to show the Log:
这里没有输出,似乎 connection.getHeaderFields() 没有返回结果。显示日志至少需要 30 秒:
10-02 16:56:25.918: V/class com.giorgi.myproject.activities.HomeActivity(2596): Header null
TESTED ON A GALAXY NEXUS
在 GALAXY NEXUS 上测试
回答by giorgiline
I've figured out what was the problem. It seems that using Java Desktop, the flag FollowRedirects is false by default (I suppose) and in Android it is true. getInstanceFollowRedirects is TRUE in both cases, so I don't really know why it works in a different way, but nevermind, the solution is perfect.
我已经弄清楚是什么问题了。似乎使用 Java 桌面,FollowRedirects 标志默认为 false (我想),而在 Android 中它是 true。getInstanceFollowRedirects 在这两种情况下都是 TRUE,所以我真的不知道为什么它以不同的方式工作,但没关系,解决方案是完美的。
So it wasn't capturing the response of the POST request, it was following some redirection and trying to get the response from another GET auto request.
所以它没有捕获 POST 请求的响应,而是遵循一些重定向并尝试从另一个 GET 自动请求获取响应。
The solution was to do: connection.setInstanceFollowRedirects(false);
解决方案是这样做: connection.setInstanceFollowRedirects(false);
The way I could know this was looking into the network traffic using a network monitor:
我知道这是使用网络监视器查看网络流量的方式:
From the Desktop application it was monitored this traffic:
从桌面应用程序监控此流量:
23 10:08:50 03/10/2012 1.3944670 javaw.exe 192.168.1.36 www.XXXXXXXXX.com HTTP HTTP:Request, POST /es/login.php {HTTP:8, TCP:7, IPv4:6}
24 10:08:50 03/10/2012 1.3954741 javaw.exe 192.168.1.36 www.XXXXXXXXX.com HTTP HTTP:HTTP Payload, URL: /es/login.php {HTTP:8, TCP:7, IPv4:6}
32 10:08:50 03/10/2012 1.9811257 javaw.exe www.XXXXXXXXX.com 192.168.1.36 HTTP HTTP:Response, HTTP/1.1, Status: Moved temporarily, URL: /es/login.php {HTTP:8, TCP:7, IPv4:6}
To monitor the traffic in Android application I had to run it in the emulator instead the phone.The result was:
为了监控 Android 应用程序中的流量,我不得不在模拟器而不是手机中运行它。结果是:
60 9:59:34 03/10/2012 4.0285909 emulator-arm.exe 192.168.1.36 XX.XX.XXX.XXX HTTP HTTP:Request, POST /es/login.php {HTTP:13, TCP:12, IPv4:11}
65 9:59:34 03/10/2012 4.1524735 emulator-arm.exe 192.168.1.36 XX.XX.XXX.XXX HTTP HTTP:HTTP Payload, URL: /es/login.php {HTTP:13, TCP:12, IPv4:11}
75 9:59:35 03/10/2012 4.6276286 emulator-arm.exe XX.XX.XXX.XXX 192.168.1.36 HTTP HTTP:Response, HTTP/1.1, Status: Moved temporarily, URL: /es/login.php {HTTP:13, TCP:12, IPv4:11}
77 9:59:35 03/10/2012 4.7095994 emulator-arm.exe 192.168.1.36 XX.XX.XXX.XXX HTTP HTTP:Request, GET /es/login.php, Query:FASID=a5e39f35325499e060f43d35bc956a45 {HTTP:13, TCP:12, IPv4:11}
311 9:59:55 03/10/2012 24.8355823 emulator-arm.exe XX.XX.XXX.XXX 192.168.1.36 HTTP HTTP:Response, HTTP/1.1, Status: Moved temporarily, URL: /es/login.php {HTTP:13, TCP:12, IPv4:11}
313 9:59:55 03/10/2012 24.9384843 emulator-arm.exe 192.168.1.36 XX.XX.XXX.XXX HTTP HTTP:Request, GET /es/main.html, Query:FASID=a5e39f35325499e060f43d35bc956a45 {HTTP:13, TCP:12, IPv4:11}
317 9:59:55 03/10/2012 25.0535818 emulator-arm.exe XX.XX.XXX.XXX 192.168.1.36 HTTP HTTP:HTTP Payload, URL: /es/main.html {HTTP:13, TCP:12, IPv4:11}
So, after applying the **connection.setInstanceFollowRedirects(false);**
the result was the expected:
所以,在应用后**connection.setInstanceFollowRedirects(false);**
,结果是预期的:
61 10:30:43 03/10/2012 4.9211205 emulator-arm.exe 192.168.1.36 XX.XX.XXX.XXX HTTP HTTP:Request, POST /es/login.php {HTTP:14, TCP:13, IPv4:12}
64 10:30:43 03/10/2012 5.0362501 emulator-arm.exe 192.168.1.36 XX.XX.XXX.XXX HTTP HTTP:HTTP Payload, URL: /es/login.php {HTTP:14, TCP:13, IPv4:12}
70 10:30:43 03/10/2012 5.5103384 emulator-arm.exe XX.XX.XXX.XXX 192.168.1.36 HTTP HTTP:Response, HTTP/1.1, Status: Moved temporarily, URL: /es/login.php {HTTP:14, TCP:13, IPv4:12}
Thank you for all your answers and interest.
感谢您的所有回答和兴趣。
回答by Emil Davtyan
It is probably something with the networking trying opening the address you are requesting in the mobile browser of the emulator or phone.
这可能与网络尝试打开您在模拟器或手机的移动浏览器中请求的地址有关。
回答by Bradsta
Make sure you've added the required permissions in the AndroidManifest.xml file.
确保您已在 AndroidManifest.xml 文件中添加了所需的权限。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
回答by Kevin Rave
I had a lot of trouble with HTTPURLConnection
After trying for a couple days, I found out, the order of setting headers matters. Here is what worked for me.
我遇到了很多麻烦HTTPURLConnection
经过几天的尝试后,我发现设置标题的顺序很重要。这对我有用。
conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Host", "yoursite.com");
conn.setRequestProperty("Authorization", "Basic " + Base64.encodeToString(toencode, Base64.DEFAULT));
conn.setRequestProperty("Accept-Charset", "UTF-8");
conn.setConnectTimeout (5000) ;
conn.setDoOutput(true);
conn.setDoInput(true);
It should work for you.
它应该适合你。