Я занимаюсь разработкой приложения для устройств Android, и одна его часть позволяет загружать и выгружать между пользователями Google Docs и хранилище устройства.Проблема, с которой я сталкиваюсь, заключается в том, что я получаю разное поведение в разных версиях Android API.Я делал большую часть разработки на API lvl 10 (Android 2.3.3).Нет проблем на виртуальном устройстве (у меня нет реального устройства для тестирования с этим API уровня или выше).На устройстве и эмуляторе API lvl 8 (2.2.x) и ниже я сталкиваюсь с требуемой ошибкой 411 длины от API Документов Google при запросе начать возобновляемый сеанс загрузки.Этого не происходит при запуске того же приложения на эмуляторе API lvl 10.
Я занимаюсь разработкой с Eclipse и использую Google API Java Client 1.4.1-beta для взаимодействия с Docs Api.Документация, которой я следую для API Документов Google, находится здесь: http://code.google.com/apis/documents/docs/3.0/developers_guide_protocol.html
Согласно указанной документации, чтобы начать возобновляемый сеанс загрузки, нужно отправить пустой запрос POST.Для «корня» пользовательских Документов Google адрес «https://docs.google.com/feeds/upload/create-session/default/private/full"». Вот как я устанавливаю заголовки для (пустого) запроса:
GoogleHeaders headers = new GoogleHeaders();
headers.contentLength = "0";
headers.gdataVersion = "3";
headers.setGoogleLogin(authToken);
//headers.contentType = getMimeType(file);
headers.setSlugFromFileName(file.getName());
headers.setApplicationName("test");
headers.set("X-Upload-Content-Length", file.length());
headers.set("X-Upload-Content-Type", getMimeType(file));
request.headers = headers;
Я должен также упомянутьчто библиотеки, которые я использую для HTTP, следующие:
com.google.api.client.googleapis.GoogleHeaders;
com.google.api.client.http.HttpRequest;
com.google.api.client.http.HttpRequestFactory;
com.google.api.client.http.HttpRequestInitializer;
com.google.api.client.http.HttpTransport;
com.google.api.client.http.HttpResponse;
com.google.api.client.http.HttpContent;
com.google.api.client.http.javanet.NetHttpTransport;
Я провёл некоторый анализ пакетов, чтобы увидеть заголовки, и вот, на разных версиях Android заголовки на самом деле не установлены одинаковоЕсли вы заметили, по умолчанию предполагается, что запрос должен быть отправлен с использованием https, поэтому я изменил его, чтобы использовать http для просмотра заголовков из пакета. Вот результаты:
Использование эмулятора Android API lvl10:
POST /feeds/upload/create-session/default/private/full?convert=false HTTP/1.1
Accept-Encoding: gzip
Authorization: **REMOVED**
Content-Length: 0
Content-Type: text/plain
GData-Version: 3
Slug: 5mbfile.txt
User-Agent: test Google-API-Java-Client/1.4.1-beta
X-Upload-Content-Length: 5242880
X-Upload-Content-Type: text/plain
Host: docs.google.com
Connection: Keep-Alive
Использование эмулятора API lvl 7:
POST /feeds/upload/create-session/default/private/full?convert=false HTTP/1.1
accept-encoding: gzip
authorization: **REMOVED**
content-type: text/plain
gdata-version: 3
slug: 5mbfile.txt
user-agent: test Google-API-Java-Client/1.4.1-beta
x-upload-content-length: 5242880
x-upload-content-type: text/plain
Host: docs.google.com
Connection: Keep-Alive
Обратите внимание на отсутствующий заголовок длины содержимого, также дело обстоит иначе. Это объясняет, почему я получаю ответ 411,но как решить эту проблему? Очевидно, моя цель - добиться одинакового поведения на всех устройствах (исключая устройства с Android 1.x по причинам, не относящимся к этой проблеме), желательно не используя конкретную версиюcode.
Честно говоря, я не могу придумать много подходящих решений, которые я мог бы применить в своем коде.Единственное, о чем я мог подумать:
transport = new NetHttpTransport();
transport.defaultHeaders.contentLength = Integer.toString(0);
Установка заголовков по-разному (не рекомендуется) в API, но безрезультатно.Фактические заголовки в запросах остаются прежними.
Установка свойства с помощью «0» или Integer.toString (0) также не имеет значения (очевидно, я немного отчаялся здесь).
Так что любая помощь или предложения, направленные на поиск решения, приветствуются.Я предоставлю больше кода, если это будет запрошено специально, а также возможно перехват пакетов для тестирования различных решений.Существует также высокая вероятность того, что это ошибка в Java Api Google Client или Android.Но какой?Если решение не найдено, у меня недостаточно глубоких знаний об Android, чтобы выяснить, где сообщить об этой (предполагаемой) ошибке.Поэтому, если вы подозреваете, что виновником действительно является не мой код, поделитесь своим мнением о том, какой компонент вызывает установку заголовков другим способом.
Edit - Algo запросил трассировку стека, вот она: http://pastebin.com/yDCCLB2P
Редактировать - я устанавливал mimetype для содержимого, хотя тело пусто.Я попытался удалить заголовок типа контента, без улучшений.Строка теперь закомментирована в приведенном выше коде.
Редактировать - я пытался решить эту проблему больше.Это трассировка стека при попытке установить заголовки двумя разными способами в одном и том же коде: http://pastebin.com/NkmFjYB3
headers.contentLength = "0";
headers.set("Content-length", "0");
При одновременном использовании они сталкиваются друг с другом.Удаление любого из них приведет к аналогичным результатам, как и раньше (411 Длина требуется из документов, а в запросе длина содержимого отсутствует).Коллизия не происходит (или не отображается в трассировке стека) при использовании одного из них и устаревшего способа (transport.defaultHeaders.contentLength = "0";) для создания запроса.При любой комбинации любого из вышеупомянутых методов либо возникает конфликт с двумя заголовками, либо запрос не имеет длины содержимого.