Criar um pacote

Opções de envio

Com a API Android Over The Air, é possível fazer upload de dados de pacote para criar um novo recurso de pacote. Eles são pacotes OTA que podem ser associados a uma ou mais configurações para que a atualização seja entregue aos dispositivos.

Fornecemos um binário para Linux e Windows a fim de facilitar os uploads de pacotes retomáveis que você pode usar livremente, em vez de implementar os protocolos descritos abaixo. Se você quiser uma integração mais profunda, use um dos protocolos descritos abaixo.

Para usá-la, primeiro você precisa criar uma conta de serviço e conseguir um arquivo de chave JSON para ela. Consulte nosso guia para criar a conta aqui.
Depois de ter o binário e o arquivo de chave, é possível executá-lo com opções de linha de comando para especificar o arquivo de chave, sua implantação e o pacote que está sendo enviado. Use --help para ver todas as opções.

Protocolos de upload

É possível fazer solicitações de upload de qualquer uma das maneiras a seguir. Especifique o método que você está usando com o cabeçalho da solicitação X-Goog-Upload-Protocol.

  • Upload de várias partes: X-Goog-Upload-Protocol: multipart. Para transferências rápidas de arquivos menores e metadados. O arquivo é transferido com os metadados que o descrevem em uma única solicitação.
  • Upload retomável: X-Goog-Upload-Protocol: resumable. Isso é importante para uma transferência confiável, especialmente de arquivos maiores. Com esse método, você usa uma solicitação de inicialização de sessão, que opcionalmente pode incluir metadados. Essa é uma boa estratégia a ser usada na maioria dos aplicativos, já que também funciona para arquivos menores. Para isso, é necessário fazer uma solicitação HTTP extra por upload.

Upload de várias partes

Essa é uma boa opção quando os dados que você está enviando são pequenos o bastante para serem enviados novamente por completo em caso de falha na conexão.

Para usar o upload em várias partes, faça uma solicitação POST para o URI /upload/package e defina X-Goog-Upload-Protocol como multipart.

Os cabeçalhos HTTP de nível superior a serem usados em uma solicitação de upload de várias partes incluem os abaixo:

  • Content-Type. Defina como "multipart/related" e inclua a string limite que você usa para identificar as partes da solicitação.
  • Content-Length. Defina com o número total de bytes no corpo da solicitação.

O corpo da solicitação é formatado como um tipo de conteúdo multipart/related [RFC2387] e contém exatamente duas partes. As partes são identificadas por uma string de limite, e a string de limite final é acompanhada por dois hifens.

Cada parte da solicitação de várias partes precisa de um cabeçalho Content-Type extra:

  1. Parte de metadados: precisa vir em primeiro lugar, e Content-Type precisa ser application/json.
  2. Parte de mídia:precisa vir depois, e Content-Type precisa ser application/zip.

Exemplo: upload de várias partes

O exemplo abaixo mostra uma solicitação de upload de várias partes para a API Android Over The Air.

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--

Se a solicitação for bem-sucedida, o servidor retornará o código de status HTTP 200 OK.

HTTP/1.1 200

Uma maneira de fazer isso facilmente é usar curl e oauth2l. Veja abaixo um exemplo de solicitação que pressupõe que você está usando uma chave de serviço. Para mais informações, consulte nossas instruções de autorização.

Exemplo de solicitação curl
    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
  

Upload retomável

Para transferir arquivos de dados de maneira mais confiável, use o protocolo de upload retomável. Esse protocolo permite retomar uma operação de upload quando uma falha de comunicação interrompe o fluxo de dados. Ele é especialmente útil se você estiver transferindo arquivos grandes e a probabilidade de uma interrupção de rede ou alguma outra falha de transmissão for alta, por exemplo, ao fazer upload de um app cliente para dispositivos móveis. Também pode reduzir o uso da largura de banda em caso de falhas de rede, porque não é necessário reiniciar os uploads de arquivos grandes desde o início.

O protocolo de upload retomável usa vários comandos:

  1. Inicie uma sessão retomável. Faça uma solicitação inicial ao URI de upload que inclua os metadados e estabeleça um local de upload retomável exclusivo.
  2. Salvar o URI da sessão retomável. Salve o URI de sessão retornado na resposta da solicitação inicial. Ele será usado nas outras solicitações da sessão.
  3. Faça upload do arquivo. Envie todo o arquivo ZIP ou parte dele para o URI de sessão retomável.

Além disso, os aplicativos que usam o upload retomável precisam ter código para retomar um upload interrompido. Se um upload for interrompido, descubra a quantidade de dados que foi recebida e retome-o daquele ponto.

Observação : o URI de upload expira após três dias.

Etapa 1: iniciar uma sessão retomável

Para iniciar um upload retomável, faça uma solicitação POST para o URI /upload/package e defina X-Goog-Upload-Protocol como resumable.

Para essa solicitação inicial, o corpo precisa conter apenas os metadados. Você transfere o conteúdo real do arquivo que quer enviar por upload nas próximas solicitações.

Use os seguintes cabeçalhos HTTP com a solicitação inicial:

  • X-Goog-Upload-Header-Content-Type. Esse é o tipo de conteúdo do arquivo que está sendo enviado e precisa ser definido como application/zip.
  • X-Goog-Upload-Command. Definido como start
  • X-Goog-Upload-Header-Content-Length. Defina com o número de bytes de dados de upload a serem transferidos em solicitações subsequentes. Se o tamanho for desconhecido no momento da solicitação, omita esse cabeçalho.
  • Content-Type. Este é o tipo de conteúdo dos metadados e precisa ser definido como application/json.
  • Content-Length. Defina conforme o número de bytes fornecidos no corpo dessa solicitação inicial.
Exemplo: solicitação de início de sessão retomável

O exemplo a seguir mostra como iniciar uma sessão retomável para a API Android Over The Air.

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" }

A próxima seção descreve como processar a resposta.

Etapa 2: salvar o URI da sessão retomável

Se a solicitação de início da sessão for bem-sucedida, o servidor da API responderá com um código de status HTTP 200 OK. Além disso, ela fornece um cabeçalho X-Goog-Upload-URL que especifica o URI de sessão retomável. O cabeçalho X-Goog-Upload-URL, mostrado no exemplo abaixo, inclui uma parte do parâmetro de consulta upload_id que fornece o ID de upload exclusivo a ser usado para essa sessão. A resposta também contém um cabeçalho X-Goog-Upload-Status, que será active se a solicitação de upload for válida e aceita. Esse status poderá ser final se o upload for rejeitado.

Exemplo: resposta de iniciação da sessão retomável

Aqui está a resposta à solicitação realizada na Etapa 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

O valor do cabeçalho X-Goog-Upload-URL, conforme mostrado na resposta de exemplo acima, é o URI de sessão que você usará como endpoint HTTP para realizar o upload real do arquivo ou consultar o status de upload.

Copie e salve o URI da sessão para poder usá-lo nas solicitações subsequentes.

Etapa 3: fazer upload do arquivo

Para fazer upload do arquivo, envie uma solicitação POST ao URI de upload recebido na etapa anterior. O formato da solicitação de upload é:

POST session_uri

Os cabeçalhos HTTP que podem ser usados ao fazer as solicitações de upload retomável de arquivos incluem:

  1. Content-Length. Defina essa opção conforme o número de bytes incluídos no upload dessa solicitação, que geralmente corresponde ao tamanho do arquivo de upload.
  2. X-Goog-Upload-Command. Defina como upload e finalize.
  3. X-Goog-Upload-Offset: especificou o deslocamento em que os bytes precisam ser gravados. Observe que os clientes precisam fazer upload dos bytes em série.
Exemplo: solicitação de upload de arquivo retomável

Esta é uma solicitação retomável para fazer upload de todo o arquivo ZIP de 2 milhões de bytes do exemplo atual.

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

Se a solicitação for bem-sucedida, o servidor responderá com um 200 Ok HTTP.

Se a solicitação de upload for interrompida ou se você receber uma resposta HTTP 503 Service Unavailable ou qualquer outra resposta 5xx do servidor, siga o procedimento descrito em Retomar um upload interrompido.


Como fazer upload do arquivo em partes

Com os uploads recuperáveis, é possível dividir um arquivo em partes e enviar várias solicitações para fazer upload de cada parte em sequência. Esse não é o método preferido porque há custos de desempenho associados às solicitações adicionais que geralmente não são necessários. Recomendamos que os clientes façam upload de todos os bytes restantes do payload e incluam o comando finalize com cada comando upload.

No entanto, talvez seja necessário usar a divisão em partes para reduzir a quantidade de dados transferidos em uma solicitação única. Essa opção também permite dar indicações sobre o andamento do upload para navegadores legados que, por padrão, não disponibilizam essa informação.


Retomar um upload interrompido

Se uma solicitação de upload for encerrada antes de receber uma resposta ou você receber uma resposta HTTP 503 Service Unavailable do servidor, será preciso retomar o upload interrompido. Para isso:

  1. Solicite o status. Consulte o status atual do upload enviando uma solicitação ao URI de upload com o X-Goog-Upload-Command definido como query.

    Observação: é possível solicitar o status entre as partes, não apenas se o upload for interrompido. Isso é útil, por exemplo, quando você quer mostrar indicações do andamento do upload a navegadores legados.

  2. Verifique o número de bytes enviados. Processe a resposta da consulta de status. O servidor usa o cabeçalho X-Goog-Upload-Size-Received na resposta para especificar quantos bytes recebeu até o momento.
  3. Envie os dados restantes. Por fim, agora que você sabe em que ponto retomar a solicitação, envie os dados restantes ou o fragmento atual. Nos dois casos, trate os dados restantes como um fragmento separado. Portanto, defina o cabeçalho X-Goog-Upload-Offset com o deslocamento adequado ao retomar o upload.
Exemplo: como retomar um upload interrompido

1) Solicite o status do upload.

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

Assim como em todos os comandos, o cliente precisa verificar o cabeçalho X-Goog-Upload-Status na resposta HTTP de um comando de consulta. Se o cabeçalho estiver presente e o valor não for active, o upload já foi encerrado.

2) Extraia o número de bytes enviados da resposta até o momento.

A resposta do servidor usa o cabeçalho X-Goog-Upload-Size-Received para indicar que ele recebeu os primeiros 43 bytes do arquivo até agora.

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

3) Retome o upload do ponto em que parou.

A solicitação a seguir retoma o upload enviando os bytes restantes do arquivo, começando pelo byte 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

Práticas recomendadas

Ao fazer upload de mídia, considere algumas práticas recomendadas relacionadas ao tratamento de erros.

  • Retome ou repita os uploads que falharem devido a interrupções de conexão ou a erros 5xx, incluindo:
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Use uma estratégia de espera exponencial se algum erro de servidor 5xx for retornado ao retomar ou repetir solicitações de upload. Esses erros podem ocorrer quando um servidor fica sobrecarregado. A espera exponencial pode ajudar a aliviar esses tipos de problemas durante períodos de alto volume de solicitações ou tráfego de rede intenso.
  • Outros tipos de solicitações não devem ser tratados por espera exponencial, mas você ainda pode repetir várias delas. Ao repetir essas solicitações, limite o número de repetições. Por exemplo, seu código pode limitar a 10 tentativas ou menos antes que um erro seja relatado.
  • Trate os erros 404 Not Found ao fazer uploads retomáveis iniciando o upload completo desde o início.

Espera exponencial

A espera exponencial é uma estratégia padrão de tratamento de erros para aplicativos de rede em que o cliente repete periodicamente uma solicitação com falha ao longo de um período crescente. Se um alto volume de solicitações ou o tráfego de rede intenso faz com que o servidor retorne erros, a espera exponencial pode ser uma boa estratégia para tratar esses erros. Por outro lado, essa não é uma estratégia relevante para tratar erros não relacionados ao volume de rede ou a tempos de resposta, como credenciais de autorização inválidas ou erros de arquivo não encontrado.

Usada corretamente, a espera exponencial aumenta a eficiência do uso da largura de banda, reduz o número de solicitações necessárias para conseguir uma resposta bem-sucedida e maximiza a capacidade de solicitações em ambientes simultâneos.

O fluxo para implementação da espera exponencial simples é o seguinte:

  1. Faça uma solicitação para a API.
  2. Receba uma resposta HTTP 503, que indica que você precisa repetir a solicitação.
  3. Aguarde um segundo + random_number_milliseconds e envie novamente a solicitação.
  4. Receba uma resposta HTTP 503, que indica que você precisa repetir a solicitação.
  5. Aguarde dois segundos + random_number_milliseconds e envie novamente a solicitação.
  6. Receba uma resposta HTTP 503, que indica que você precisa repetir a solicitação.
  7. Aguarde 4 segundos + random_number_milliseconds e repita a solicitação.
  8. Receba uma resposta HTTP 503, que indica que você deve repetir a solicitação.
  9. Aguarde 8 segundos + random_number_milliseconds e repita a solicitação.
  10. Receba uma resposta HTTP 503, que indica que você deve repetir a solicitação.
  11. Aguarde 16 segundos + random_number_milliseconds e repita a solicitação.
  12. Pare. Informe ou registre um erro.

No fluxo acima, random_number_milliseconds é um número aleatório de milissegundos menor ou igual a 1.000. Isso é necessário porque a introdução de um pequeno atraso aleatório ajuda a distribuir a carga de maneira mais uniforme e a evitar a possibilidade de sobrecarga do servidor. Após cada espera, é preciso redefinir o valor de random_number_milliseconds.

Observação: a espera é sempre (2 ^ n) + random_number_milliseconds, em que n é um número inteiro monótono crescente inicialmente definido como 0. O número inteiro n é incrementado em 1 para cada iteração (cada solicitação).

O algoritmo é definido para terminar quando n for 5. Esse limite impede que os clientes fiquem tentando infinitamente e gera um atraso total de cerca de 30 segundos antes de uma solicitação ser considerada "um erro irrecuperável". Um número máximo maior de tentativas não é um problema, especialmente se um upload longo estiver em andamento. No entanto, use um atraso de repetição aceitável, por exemplo, menos de um minuto.