Создать пакет

Варианты загрузки

API Android Over The Air позволяет загружать данные пакета для создания нового ресурса пакета. Это пакеты OTA, которые можно связать с одной или несколькими конфигурациями, чтобы обновление доставлялось на устройства.

Мы предоставляем двоичный файл для Linux и Windows для облегчения возобновляемой загрузки пакетов, который вы можете использовать вместо реализации протоколов, описанных ниже. Если вы желаете более глубокой интеграции, используйте один из протоколов, описанных ниже.

Чтобы использовать его, сначала необходимо создать учетную запись службы и получить файл ключа JSON для этой учетной записи. Пожалуйста, ознакомьтесь с нашим руководством по созданию учетной записи здесь .
Получив двоичный файл и файл ключа, вы можете запустить его с параметрами командной строки, чтобы указать файл ключа, ваше развертывание и загружаемый пакет. Пожалуйста, используйте --help , чтобы увидеть все варианты.

Протоколы загрузки

Вы можете отправлять запросы на загрузку любым из следующих способов. Укажите используемый метод с заголовком запроса X-Goog-Upload-Protocol .

  • Многочастная загрузка : X-Goog-Upload-Protocol: multipart . Для быстрой передачи небольших файлов и метаданных; передает файл вместе с метаданными, которые его описывают, и все это в одном запросе.
  • Возобновляемая загрузка : X-Goog-Upload-Protocol: resumable . Для надежной передачи, особенно важно для файлов большего размера. С помощью этого метода вы используете запрос, инициирующий сеанс, который при необходимости может включать метаданные. Это хорошая стратегия для большинства приложений, поскольку она также работает для файлов меньшего размера за счет одного дополнительного HTTP-запроса на каждую загрузку.

Многочастная загрузка

Это хороший выбор, если отправляемые вами данные достаточно малы, чтобы их можно было загрузить снова целиком в случае сбоя соединения.

Чтобы использовать многочастную загрузку, выполните POST запрос к URI /upload/package и установите X-Goog-Upload-Protocol значение multipart .

HTTP-заголовки верхнего уровня, которые следует использовать при выполнении запроса на многочастную загрузку, включают:

  • Content-Type . Установите значение «многочастный/связанный» и включите граничную строку, которую вы используете для идентификации частей запроса.
  • Content-Length . Устанавливается общее количество байтов в теле запроса.

Тело запроса отформатировано как multipart/related тип контента [ RFC2387 ] и содержит ровно две части. Части идентифицируются граничной строкой, а за последней граничной строкой следуют два дефиса.

Для каждой части составного запроса требуется дополнительный заголовок Content-Type :

  1. Часть метаданных: должна быть первой, а Content-Type должен быть application/json .
  2. Медиа-часть: должна быть второй, а Content-Type должен быть application/zip .

Пример: многочастная загрузка

В приведенном ниже примере показан составной запрос на загрузку для Android Over The Air API.

POST /upload/package HTTP/1.1
Host: androidovertheair.googleapis.com
Authorization: Bearer your_auth_token
Content-Type: multipart/related; boundary=BOUNDARY
Content-Length: number_of_bytes_in_entire_request_body

--BOUNDARY
Content-Type: application/json; charset=UTF-8

{"deployment": "id", "package_title": "title" }
--BOUNDARY
Content-Type: application/zip; charset=UTF-8

Package ZIP
--BOUNDARY--

Если запрос успешен, сервер возвращает код состояния HTTP 200 OK

HTTP/1.1 200

Самый простой способ добиться этого — использовать curl и oauth2l . Ниже приведен пример запроса, в котором предполагается, что вы используете служебный ключ (дополнительную информацию см. в разделе авторизация ).

Пример запроса на скручивание
    JSON={"deployment": "id", "package_title": "title" }
    SERVICE_KEY_FILE=path to your service key json file
    curl \
    -H "$(./oauth2l header --json $SERVICE_KEY_FILE android_partner_over_the_air)" \
    -H "Host: androidovertheair.googleapis.com" \
    -H "X-Goog-Upload-Protocol: multipart" \
    -H "Content-Type: multipart/form-data" \
    -F "json=$JSON;type=application/json" \
    -F "data=@update.zip;type=application/zip" \
    androidovertheair.googleapis.com/upload/package
  

Возобновляемая загрузка

Для более надежной загрузки файлов данных вы можете использовать протокол возобновляемой загрузки. Этот протокол позволяет возобновить операцию загрузки после того, как сбой связи прервал поток данных. Это особенно полезно, если вы передаете большие файлы и высока вероятность сбоя сети или какого-либо другого сбоя передачи, например, при загрузке из мобильного клиентского приложения. Это также может снизить использование полосы пропускания в случае сбоев сети, поскольку вам не придется перезапускать загрузку больших файлов с самого начала.

Протокол возобновляемой загрузки использует несколько команд:

  1. Запустите возобновляемый сеанс . Сделайте первоначальный запрос к URI загрузки, который включает метаданные и устанавливает уникальное место для возобновления загрузки.
  2. Сохраните URI возобновляемого сеанса . Сохраните URI сеанса, возвращенный в ответе на первоначальный запрос; вы будете использовать его для остальных запросов в этом сеансе.
  3. Загрузите файл . Отправьте весь или часть ZIP-файла на URI возобновляемого сеанса.

Кроме того, приложения, использующие возобновляемую загрузку, должны иметь код для возобновления прерванной загрузки . Если загрузка прервана, выясните, какой объем данных был успешно получен, а затем возобновите загрузку, начиная с этого момента.

Примечание. Срок действия URI загрузки истекает через 3 дня.

Шаг 1. Запустите возобновляемый сеанс.

Чтобы инициировать возобновляемую загрузку, выполните POST запрос к URI /upload/package и установите X-Goog-Upload-Protocol значение resumable .

Для этого инициирующего запроса тело должно содержать только метаданные; вы будете передавать фактическое содержимое файла, который хотите загрузить, в последующих запросах.

Используйте следующие HTTP-заголовки с первоначальным запросом:

  • X-Goog-Upload-Header-Content-Type . Это тип содержимого загружаемого файла, для которого должно быть установлено значение application/zip .
  • X-Goog-Upload-Command . start
  • X-Goog-Upload-Header-Content-Length . Установите количество байтов загружаемых данных, которые будут переданы в последующих запросах. Если длина неизвестна на момент этого запроса, вы можете опустить этот заголовок.
  • Content-Type . Это тип содержимого метаданных, для которого должно быть установлено значение application/json .
  • Content-Length . Установите количество байтов, указанное в теле этого первоначального запроса.
Пример: запрос на инициирование возобновляемого сеанса

В следующем примере показано, как инициировать возобновляемый сеанс для Android Over The Air API.

POST /upload/package HTTP/1.1
Host: android/over-the-air.googleapis.com
Authorization: Bearer your_auth_token
Content-Length: 38
Content-Type: application/json; charset=UTF-8
X-Goog-Upload-Command: start
X-Goog-Upload-Header-Content-Type: application/zip
X-Goog-Upload-Header-Content-Length: 2000000

{"deployment": "id", "package_title": "title" }

В следующем разделе описывается, как обрабатывать ответ.

Шаг 2. Сохраните URI возобновляемого сеанса.

Если запрос на инициацию сеанса успешен, сервер API отвечает кодом состояния HTTP 200 OK . Кроме того, он предоставляет заголовок X-Goog-Upload-URL , который указывает URI возобновляемого сеанса. Заголовок X-Goog-Upload-URL , показанный в примере ниже, включает в себя часть параметра запроса upload_id , которая дает уникальный идентификатор загрузки, который будет использоваться для этого сеанса. Ответ также содержит заголовок X-Goog-Upload-Status , который будет active , если запрос на загрузку действителен и принят. Этот статус может быть final , если загрузка была отклонена.

Пример: ответ на инициацию возобновляемого сеанса

Вот ответ на запрос на шаге 1:

HTTP/1.1 200 OK
X-Goog-Upload-Status: active
X-Goog-Upload-URL: androidovertheair.googleapis.com/?upload_id=xa298sd_sdlkj2
Content-Length: 0

Значение заголовка X-Goog-Upload-URL , как показано в приведенном выше примере ответа, представляет собой URI сеанса, который вы будете использовать в качестве конечной точки HTTP для фактической загрузки файла или запроса статуса загрузки.

Скопируйте и сохраните URI сеанса, чтобы использовать его для последующих запросов.

Шаг 3. Загрузите файл.

Чтобы загрузить файл, отправьте запрос POST на URI загрузки, полученный на предыдущем шаге. Формат запроса на загрузку:

POST session_uri

Заголовки HTTP, используемые при отправке возобновляемых запросов на загрузку файлов, включают:

  1. Content-Length . Установите это количество байтов, которые вы загружаете в этом запросе, что обычно соответствует размеру загружаемого файла.
  2. X-Goog-Upload-Command . Установите это для upload и finalize .
  3. X-Goog-Upload-Offset . Это задавало смещение, по которому должны записываться байты. Обратите внимание, что клиенты должны загружать байты последовательно.
Пример: запрос на возобновляемую загрузку файла

Вот возобновляемый запрос на загрузку всего ZIP-файла размером 2 000 000 байт для текущего примера.

POST /?upload_id=xa298sd_sdlkj2 HTTP/1.1
Host: androidovertheair.googleapis.com
X-Goog-Upload-Protocol: resumable
X-Goog-Upload-Command: upload, finalize
X-Goog-Upload-Offset: 0
Content-Length: 2000000
Content-Type: application/zip

bytes 0-1999999

Если запрос успешен, сервер отвечает HTTP 200 Ok .

Если запрос на загрузку прерван или вы получили сообщение HTTP 503 Service Unavailable или любой другой ответ 5xx от сервера, выполните процедуру, описанную в разделе «Возобновление прерванной загрузки ».


Загрузка файла частями

Благодаря возобновляемым загрузкам вы можете разбить файл на фрагменты и отправить серию запросов для последовательной загрузки каждого фрагмента. Это не предпочтительный подход, поскольку дополнительные запросы связаны с затратами на производительность, и обычно в этом нет необходимости. Мы рекомендуем клиентам загружать все оставшиеся байты полезных данных и включать команду finalize в каждую команду upload .

Однако вам может потребоваться использовать фрагментирование, чтобы уменьшить объем данных, передаваемых в любом отдельном запросе. Он также позволяет вам выполнять такие действия, как предоставление индикаторов хода загрузки для устаревших браузеров, которые по умолчанию не имеют поддержки процесса загрузки.


Возобновить прерванную загрузку

Если запрос на загрузку прерывается до получения ответа или вы получаете ответ HTTP 503 Service Unavailable от сервера, вам необходимо возобновить прерванную загрузку. Сделать это:

  1. Статус запроса. Запросите текущий статус загрузки, отправив запрос к URI загрузки с X-Goog-Upload-Command установленным на query .

    Примечание. Вы можете запрашивать статус между фрагментами, а не только в том случае, если загрузка прервана. Это полезно, например, если вы хотите отображать индикаторы хода загрузки для устаревших браузеров.

  2. Получить количество загруженных байтов. Обработайте ответ на запрос статуса. Сервер использует заголовок X-Goog-Upload-Size-Received в своем ответе, чтобы указать, сколько байтов он уже получил.
  3. Загрузите оставшиеся данные. Наконец, теперь, когда вы знаете, где возобновить запрос, отправьте оставшиеся данные или текущий фрагмент. Обратите внимание, что в любом случае вам необходимо рассматривать оставшиеся данные как отдельный фрагмент, поэтому вам необходимо установить для заголовка X-Goog-Upload-Offset правильное смещение при возобновлении загрузки.
Пример: возобновление прерванной загрузки

1) Запросить статус загрузки.

POST /?upload_id=xa298sd_sdlkj2 HTTP/1.1
Host: androidovertheair.googleapis.com
X-Goog-Upload-Command: query

Как и в случае со всеми командами, клиент должен проверить заголовок X-Goog-Upload-Status в ответе HTTP на команду запроса. Если заголовок присутствует и значение не active , значит, загрузка уже прекращена.

2) Извлеките количество загруженных на данный момент байтов из ответа.

В ответе сервера используется заголовок X-Goog-Upload-Size-Received указывающий, что на данный момент он получил первые 43 байта файла.

HTTP/1.1 200 OK
X-Goog-Upload-Status: active
X-Goog-Upload-Size-Received: 42

3) Возобновите загрузку с того места, где она была прервана.

Следующий запрос возобновляет загрузку, отправляя оставшиеся байты файла, начиная с байта 43.

POST /?upload_id=xa298sd_sdlkj2 HTTP/1.1
Host: androidovertheair.googleapis.com
X-Goog-Upload-Command: upload, finalize
Content-Length: 1999957
X-Goog-Upload-Offset: 43

bytes 43-1999999

Лучшие практики

При загрузке мультимедиа полезно знать некоторые рекомендации, связанные с обработкой ошибок.

  • Возобновите или повторите загрузку, которая не удалась из-за прерывания соединения или ошибок 5xx , в том числе:
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Используйте стратегию экспоненциальной задержки , если при возобновлении или повторной попытке запросов на загрузку возвращается какая-либо ошибка сервера 5xx . Эти ошибки могут возникнуть, если сервер перегружен. Экспоненциальная отсрочка может помочь смягчить такого рода проблемы в периоды большого объема запросов или интенсивного сетевого трафика.
  • Другие типы запросов не должны обрабатываться экспоненциальной задержкой, но вы все равно можете повторить некоторые из них. При повторной попытке этих запросов ограничьте количество повторных попыток. Например, ваш код может ограничить количество повторов до 10 или меньше, прежде чем сообщать об ошибке.
  • Обрабатывайте ошибки 404 Not Found при возобновлении загрузки, начиная всю загрузку с самого начала.

Экспоненциальный откат

Экспоненциальная отсрочка — это стандартная стратегия обработки ошибок для сетевых приложений, при которой клиент периодически повторяет неудачный запрос в течение увеличивающегося промежутка времени. Если из-за большого объема запросов или интенсивного сетевого трафика сервер возвращает ошибки, экспоненциальная отсрочка может быть хорошей стратегией для обработки этих ошибок. И наоборот, это неподходящая стратегия для борьбы с ошибками, не связанными с объемом сети или временем ответа, такими как неверные учетные данные авторизации или ошибки «файл не найден».

При правильном использовании экспоненциальная отсрочка повышает эффективность использования полосы пропускания, уменьшает количество запросов, необходимых для получения успешного ответа, и максимизирует пропускную способность запросов в параллельных средах.

Порядок реализации простого экспоненциального отката следующий:

  1. Сделайте запрос к API.
  2. Получите ответ HTTP 503 , который указывает, что вам следует повторить запрос.
  3. Подождите 1 секунду + случайное_число_миллисекунд и повторите запрос.
  4. Получите ответ HTTP 503 , который указывает, что вам следует повторить запрос.
  5. Подождите 2 секунды + случайное_число_миллисекунд и повторите запрос.
  6. Получите ответ HTTP 503 , который указывает, что вам следует повторить запрос.
  7. Подождите 4 секунды + случайное_число_миллисекунд и повторите запрос.
  8. Получите ответ HTTP 503 , который указывает, что вам следует повторить запрос.
  9. Подождите 8 секунд + случайное_число_миллисекунд и повторите запрос.
  10. Получите ответ HTTP 503 , который указывает, что вам следует повторить запрос.
  11. Подождите 16 секунд + случайное_число_миллисекунд и повторите запрос.
  12. Останавливаться. Сообщите или зарегистрируйте ошибку.

В приведенном выше потоке случайное_число_миллисекунды — это случайное число миллисекунд, меньшее или равное 1000. Это необходимо, поскольку введение небольшой случайной задержки помогает распределить нагрузку более равномерно и избежать возможности затормозить сервер. Значение Random_number_milli Seconds необходимо переопределять после каждого ожидания.

Примечание. Ожидание всегда равно (2 ^ n) + случайное_число_миллисекунд, где n — монотонно возрастающее целое число, изначально определенное как 0. Целое число n увеличивается на 1 для каждой итерации (каждого запроса).

Алгоритм настроен на завершение, когда n равно 5. Этот предел не позволяет клиентам бесконечно повторять попытки и приводит к общей задержке около 32 секунд, прежде чем запрос будет считаться «неустранимой ошибкой». Большее максимальное количество повторов допустимо, особенно если идет длительная загрузка; просто не забудьте ограничить задержку повторной попытки чем-то разумным, скажем, менее одной минуты.