2011-11-18 51 views
11

Galaxy Nexus của tôi đã đến hôm nay và một trong những điều đầu tiên tôi làm là tải ứng dụng của tôi lên đó để tôi có thể chứng minh cho bạn bè của mình. Một phần chức năng của nó liên quan đến việc nhập Nguồn cấp RSS từ Google Reader. Tuy nhiên, khi cố gắng này, tôi đã nhận được 405 lỗi phương pháp không được phép.ICS Android 4.0 chuyển HttpURLKết nối yêu cầu GET thành yêu cầu POST

Vấn đề này là đặc trưng của Ice Cream Sandwich. Mã tôi đã đính kèm hoạt động tốt trên Gingerbread và Honeycomb. Tôi đã truy tìm lỗi đến thời điểm kết nối được thực hiện, khi yêu cầu GET biến đổi một cách kỳ diệu thành một yêu cầu 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; 
    } 
} 

Có bất kỳ điều gì có thể gây ra sự cố này không? Chức năng này có thể được mã hóa tốt hơn để tránh vấn đề này không?

Rất cám ơn trước.

Trả lời

20

Hành vi này được mô tả trong Android Developers: HttpURLConnection

HttpURLConnection sử dụng phương thức GET theo mặc định. Nó sẽ sử dụng POST nếu setDoOutput (true) đã được gọi.

Điều lạ lẫm là điều này chưa thực sự là hành vi cho đến 4.0, vì vậy tôi sẽ tưởng tượng nó sẽ phá vỡ nhiều ứng dụng đã xuất bản hiện có.

Có thêm thông tin này tại số Android 4.0 turns GET into POST.

8

Loại bỏ điều này:

connection.setRequestProperty("Content-Type","application/x-www-form-urlendcoded"); 

này cho các API này là một POST.

CẬP NHẬT về cách nó có thể được thực hiện thông qua 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(); 
    } 
} 
+0

Không. Loại bỏ dòng đó không tạo ra sự khác biệt nào cả. –

+1

Ok, sau đó bạn cũng có thể thử đi với HttpClient. –

+0

@Michael Dodd: kiểm tra phần UPDATE –

10

Loại bỏ dòng này làm việc cho tôi:

connection.setDoOutput(true); 

4,0 nghĩ với dòng này nó chắc chắn phải là POST.

+2

Cảm ơn Fedor, Công việc của tôi cũng vậy. Tôi có cùng một vấn đề với phương thức GET. Khi tôi gọi phương thức GET với setDoOutPut (true), tôi nhận được Http 405: Thông báo Method Not Allowed đã được trả về. Cảm ơn một lần nữa. – PrashantAdesara

2

Tôi đã phát hiện ra rằng trước ICS người ta có thể nhận được ngay với thực hiện một POST cơ thể ít mà không cung cấp một giá trị Content-Length, tuy nhiên sau ICS bạn phải thiết lập Content-Length: 0.

3

Đây là một mà đã cho tôi - về cơ bản bằng cách thiết lập setDoOutput (true) nó buộc một yêu cầu POST khi bạn thực hiện kết nối, thậm chí nếu bạn chỉ định đây là một GET trong setRequestMethod:

HttpURLConnection sử dụng phương thức GET theo mặc định . Nó sẽ sử dụng POST nếu setDoOutput (true) đã được gọi. Các phương thức HTTP khác (OPTIONS, HEAD, PUT, DELETE và TRACE) có thể được sử dụng với setRequestMethod (String).

Điều này khiến tôi trở lại - rất bực bội ...

Xem http://developer.android.com/reference/java/net/HttpURLConnection.html và chuyển đến Phương thức HTTP tiêu đề

Các vấn đề liên quan