Android 4.0 ICS 将 HttpURLConnection GET 请求转换为 POST 请求
Posted
技术标签:
【中文标题】Android 4.0 ICS 将 HttpURLConnection GET 请求转换为 POST 请求【英文标题】:Android 4.0 ICS turning HttpURLConnection GET requests into POST requests 【发布时间】:2012-01-01 11:57:47 【问题描述】:我的 Galaxy Nexus 今天到货了,我做的第一件事就是将我的应用程序加载到它上面,这样我就可以向我的朋友们展示它。它的部分功能涉及从 Google Reader 导入 RSS Feed。但是,在尝试此操作时,我收到了 405 Method Not Allowed 错误。
这个问题是冰淇淋三明治特有的。我附上的代码在 Gingerbread 和 Honeycomb 上运行良好。我已经将错误追溯到建立连接的那一刻,当时 GET 请求神奇地变成了 POST 请求。
/**
* Get the authentication token from Google
* @param auth The Auth Key generated in getAuth()
* @return The authentication token
*/
private String getToken(String auth)
final String tokenAddress = "https://www.google.com/reader/api/0/token";
String response = "";
URL tokenUrl;
try
tokenUrl = new URL(tokenAddress);
HttpURLConnection connection = (HttpURLConnection) tokenUrl.openConnection();
connection.setRequestMethod("GET");
connection.addRequestProperty("Authorization", "GoogleLogin auth=" + auth);
connection.setRequestProperty("Content-Type","application/x-www-form-urlendcoded");
connection.setUseCaches(false);
connection.setDoOutput(true);
Log.d(TAG, "Initial method: " + connection.getRequestMethod()); // Still GET at this point
try
connection.connect();
Log.d(TAG, "Connected. Method is: " + connection.getRequestMethod()); // Has now turned into POST, causing the 405 error
InputStream in = new BufferedInputStream(connection.getInputStream());
response = convertStreamToString(in);
connection.disconnect();
return response;
catch (Exception e)
Log.d(TAG, "Something bad happened, response code was " + connection.getResponseCode()); // Error 405
Log.d(TAG, "Method was " + connection.getRequestMethod()); // POST again
Log.d(TAG, "Auth string was " + auth);
e.printStackTrace();
connection.disconnect();
return null;
catch(Exception e)
// Stuff
Log.d(TAG, "Something bad happened.");
e.printStackTrace();
return null;
有什么可能导致这个问题吗?能否更好地对该函数进行编码以避免此问题?
非常感谢。
【问题讨论】:
【参考方案1】:android Developers: HttpURLConnection 中描述了此行为
HttpURLConnection 默认使用 GET 方法。它将使用 POST 如果 setDoOutput(true) 已被调用。
但奇怪的是,直到 4.0 才真正出现这种行为,所以我想它会破坏许多现有的已发布应用程序。
Android 4.0 turns GET into POST 有更多相关信息。
【讨论】:
【参考方案2】:删除这条线对我有用:
connection.setDoOutput(true);
4.0 认为这行肯定应该是 POST。
【讨论】:
感谢 Fedor,它也为我工作。我对 GET 方法有同样的问题。当我用 setDoOutPut(true) 调用 GET 方法时,我得到了 Http 405: Method Not Allowed 消息被返回。再次感谢。【参考方案3】:摆脱这个:
connection.setRequestProperty("Content-Type","application/x-www-form-urlendcoded");
这告诉 API 这是一个 POST。
更新关于如何通过HttpClient
:
String response = null;
HttpClient httpclient = null;
try
HttpGet httpget = new HttpGet(yourUrl);
httpget.setHeader("Authorization", "GoogleLogin auth=" + auth);
httpclient = new DefaultHttpClient();
HttpResponse httpResponse = httpclient.execute(httpget);
final int statusCode = httpResponse.getStatusLine().getStatusCode();
if (statusCode != HttpStatus.SC_OK)
throw new Exception("Got HTTP " + statusCode
+ " (" + httpResponse.getStatusLine().getReasonPhrase() + ')');
response = EntityUtils.toString(httpResponse.getEntity(), HTTP.UTF_8);
catch (Exception e)
e.printStackTrace();
// do some error processing here
finally
if (httpclient != null)
httpclient.getConnectionManager().shutdown();
【讨论】:
不。删除那条线根本没有区别。 好的,那你也可以试试HttpClient。 @Michael Dodd:查看更新部分 我也有同样的问题,我没有设置“Content-Type”属性,但是还是不行…… 编辑:nvm,由下面的@djh 答案解决(如果 setDoOutput(true) 已被调用,它将使用 POST)【参考方案4】:这让我着迷——基本上是通过设置 setDoOutput(true) 来强制在您建立连接时发出 POST 请求,即使您在 setRequestMethod 中指定这是一个 GET:
HttpURLConnection 默认使用 GET 方法。它将使用 POST 如果 setDoOutput(true) 已被调用。其他 HTTP 方法(OPTIONS、HEAD、 PUT、DELETE 和 TRACE) 可以与 setRequestMethod(String) 一起使用。
这让我很反感 - 非常令人沮丧......
查看 http://developer.android.com/reference/java/net/HttpURLConnection.html 并转到 HTTP 方法标题
【讨论】:
【参考方案5】:我发现,在 ICS 之前,可以在不提供 Content-Length 值的情况下制作无正文的 POST,但是在 ICS 之后,您必须设置 Content-Length: 0。
【讨论】:
以上是关于Android 4.0 ICS 将 HttpURLConnection GET 请求转换为 POST 请求的主要内容,如果未能解决你的问题,请参考以下文章
搭载Android 4.0是啥意思 和安卓4.0操作系统 有啥区别
Android 4.0 org.apache.http.conn.ConnectTimeoutException:连接到...超时
以 min API 14 (ICS) 为目标时,最好使用 FragmentActivity(或 ActionBarActivity)或系统 Activity?