我的Galaxy Nexus今天到了,我做的第一件事就是将我的应用程序加载到它上面,这样我就可以向朋友们展示它了。其部分功能涉及从Google阅读器导入RSS源。但是,在尝试这个时,我得到了405个方法不允许错误。
这个问题是冰淇淋三明治特有的。我附上的代码在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;
}
}
有什么可能导致这个问题吗?这个功能可以更好地编码以避免这个问题吗?
非常感谢提前。
答案 0 :(得分:20)
Android Developers: HttpURLConnection
中描述了此行为HttpURLConnection默认使用GET方法。它将使用POST if setDoOutput(true)已被调用。
但奇怪的是,直到4.0,这实际上并没有出现这种情况,所以我认为它会破坏许多已发布的应用程序。
答案 1 :(得分:10)
删除此行对我有用:
connection.setDoOutput(true);
4.0认为这行应该绝对是POST。
答案 2 :(得分:8)
摆脱这个:
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();
}
}
答案 3 :(得分:3)
这是我的一个 - 基本上通过设置setDoOutput(true)它会在你建立连接时强制POST请求,即使你在setRequestMethod 中指定这是一个GET:
HttpURLConnection默认使用GET方法。它将使用POST if setDoOutput(true)已被调用。其他HTTP方法(OPTIONS,HEAD, PUT,DELETE和TRACE)可以与setRequestMethod(String)一起使用。
这让我有一段时间了 - 非常令人沮丧...
请参阅http://developer.android.com/reference/java/net/HttpURLConnection.html并转到HTTP方法标题
答案 4 :(得分:2)
我发现pre-ICS可以在没有提供Content-Length值的情况下完成无体操作的POST,但是在ICS之后你必须设置Content-Length:0。