Intereting Posts
Значение по умолчанию в ListPreference из array.xml Причин: retrofit.RetrofitError: метод POST должен иметь тело запроса Подробное объяснение профиля из «adb shell dumpsys meminfo my-app-name»? Parse.com: с помощью parseUser, как я могу сохранить данные в столбце, который я создал в parse из класса? Пользовательский Android-компонент сбой приложения на раздувание Как использовать GWT-RequestFactory в Android SyncAdapter (всегда получая ValidationTool-Error) Любой способ узнать, загружено ли устройство с fastboot? Как обновить TextView от другого класса Как закрыть / убить приложение на устройстве Android с помощью appium? Разрешить пользователю кликнуть на рекламу, чтобы разблокировать функции Как установить правый край ящика навигатора? Просмотреть стек активности в Android Как использовать привратник с клиентом android? Ошибка Json Parsing в моем проекте Вызовите «Maven Project Builder» в Eclipse при запуске как -> Android-приложение (или вручную)

Android 4.0 ICS превращает HttpURLConnection GET запросы в запросы POST

Моя Galaxy Nexus прибыла сегодня, и одна из первых вещей, которую я сделал, это загрузить мое приложение, чтобы я мог продемонстрировать это своим друзьям. Часть его функций включает импорт RSS-каналов из Google Reader. Однако при попытке этого я получал ошибки 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; } } 

Есть ли что-то, что может вызвать эту проблему? Может ли эта функция лучше кодироваться, чтобы избежать этой проблемы?

Спасибо заранее.

    Такое поведение описано в Android Developers: HttpURLConnection

    HttpURLConnection использует метод GET по умолчанию. Он будет использовать POST, если был вызван setDoOutput (true).

    Странно, однако, что это не было поведением до 4.0, поэтому я бы предположил, что это сломает многие существующие опубликованные приложения.

    Более того, на Android 4.0 становится GET в POST .

    Удаление этой строки работало для меня:

     connection.setDoOutput(true); 

    4.0 думает, что эта строка обязательно должна быть POST.

    Избавьтесь от этого:

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

    Это говорит API, что это POST.

    UPDATE о том, как это можно сделать с помощью 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(); } } 

    Это то, что меня достало – в основном, установив setDoOutput (true), он вызывает запрос POST при создании соединения, даже если вы укажете, что это GET в setRequestMethod :

    HttpURLConnection использует метод GET по умолчанию. Он будет использовать POST, если был вызван setDoOutput (true). Другие методы HTTP (OPTIONS, HEAD, PUT, DELETE и TRACE) могут использоваться с setRequestMethod (String).

    Это застало меня некоторое время назад – очень расстраивающе …

    См. http://developer.android.com/reference/java/net/HttpURLConnection.html и перейдите в раздел «Методы HTTP»

    Я обнаружил, что pre-ICS может уйти с помощью без POST без предоставления значения Content-Length, однако после ICS вы должны установить Content-Length: 0.