Crea un pacchetto

Opzioni di caricamento

L'API Android Over The Air ti consente di caricare i dati dei pacchetti per creare una nuova risorsa Package. Si tratta di Pacchetti OTA che possono essere associati a una o più configurazioni in modo da pubblicare l'aggiornamento ai dispositivi.

Forniamo un programma binario per Linux e Windows per facilitare il ripristino dei caricamenti di pacchetti, possono essere utilizzati liberamente anziché implementare i protocolli descritti di seguito. Se desideri un'analisi più approfondita integrazione, utilizza uno dei protocolli descritti di seguito.

Per utilizzarlo, devi prima creare un account di servizio e ottenere un file chiave JSON per quell'account. Consulta la nostra guida per la creazione dell'account qui.
Una volta che hai il file binario e il file della chiave, puoi eseguirlo utilizzando le opzioni della riga di comando per specificare il file della chiave, il deployment e il pacchetto che stai caricando. Usa --help per visualizzare tutte le opzioni.

Protocolli di caricamento

Puoi effettuare richieste di caricamento in uno dei seguenti modi. Specifica il metodo che stai utilizzando con l'intestazione della richiesta X-Goog-Upload-Protocol.

  • Caricamento di più parti: X-Goog-Upload-Protocol: multipart. Per un trasferimento rapido file e metadati più piccoli; trasferisce il file insieme ai metadati che lo descrivono, il tutto in un'unica richiesta.
  • Caricamento ripristinabile: X-Goog-Upload-Protocol: resumable. Per trasferimenti affidabili, particolarmente importanti in caso di richieste . Con questo metodo, utilizzi una richiesta di avvio della sessione che, facoltativamente, può includere metadati. Questa è una buona strategia da usare per la maggior parte perché funziona anche per file più piccoli al costo di una richiesta HTTP aggiuntiva per caricamento.

Caricamento di più parti

È una buona scelta se i dati che invii sono di dimensioni ridotte abbastanza per eseguire di nuovo il caricamento completo in caso di errore di connessione.

Per utilizzare il caricamento di più parti, effettua una richiesta POST a /upload/package URI e imposta X-Goog-Upload-Protocol su multipart.

Le intestazioni HTTP di primo livello da utilizzare quando si effettua una richiesta di caricamento multiparte includono:

  • Content-Type. Imposta su multipart/related e includi la stringa di confine a cui stai per identificare le parti della richiesta.
  • Content-Length. Impostato sul numero totale di byte nel corpo della richiesta.

Il corpo della richiesta è formattato come contenuto multipart/related digita [RFC2387] e contiene esattamente due parti. Le parti sono identificate da una stringa di confine, e la stringa limite finale è seguita da due trattini.

Ogni parte della richiesta con più parti richiede un'intestazione Content-Type aggiuntiva:

  1. Parte relativa ai metadati: deve essere inviata per prima e il valore Content-Type deve essere application/json.
  2. Parte multimediale: deve essere seconda e Content-Type deve essere application/zip.

Esempio: caricamento di più parti

L'esempio seguente mostra una richiesta di caricamento con più parti per l'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 la richiesta ha esito positivo, il server restituisce il codice di stato HTTP 200 OK

HTTP/1.1 200

Un modo per farlo facilmente è usare curl e oauth2l. Di seguito è riportato un esempio di richiesta parte dal presupposto che tu stia utilizzando una chiave di servizio (vedi le nostre autorizzazione come fare per ulteriori informazioni).

Esempio di richiesta 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
  

Caricamento ripristinabile

Per caricare i file di dati in modo più affidabile, puoi utilizzare il protocollo di caricamento ripristinabile. Questo protocollo consente di riprendere un'operazione di caricamento dopo che un errore di comunicazione ha interrotto il flusso di dati. it è particolarmente utile se si stanno trasferendo file di grandi dimensioni e se si verificano interruzioni di rete o altri errori di trasmissione sono elevati, ad esempio, durante il caricamento da un'app client mobile. it puoi anche ridurre l'utilizzo della larghezza di banda in caso di guasti di rete, perché non devi riavvia dall'inizio i caricamenti di file di grandi dimensioni.

Il protocollo di caricamento ripristinabile utilizza diversi comandi:

  1. Avvia una sessione ripristinabile. Effettua una richiesta iniziale all'URI di caricamento che includa il metadati e stabilisce un percorso di caricamento univoco ripristinabile.
  2. Salva l'URI della sessione ripristinabile. Salva l'URI della sessione restituito nella la risposta della richiesta iniziale; e la utilizzerai per le richieste rimanenti di questa sessione.
  3. Carica il file. Invia tutto o parte del file ZIP all'URI della sessione ripristinabile.

Inoltre, le app che utilizzano il caricamento ripristinabile devono disporre di codice per riprendere un caricamento interrotto. Se un caricamento viene interrotta, verifica la quantità di dati ricevuti e riprendi il caricamento a partire da quel momento.

Nota : l'URI di caricamento scade dopo 3 giorni.

Passaggio 1: avvia una sessione ripristinabile

Per avviare un caricamento ripristinabile, effettua una richiesta POST a /upload/package URI e imposta X-Goog-Upload-Protocol su resumable.

Per questa richiesta di avvio, il corpo deve contenere solo i metadati. trasferisci l'effettiva del file da caricare nelle richieste successive.

Utilizza le seguenti intestazioni HTTP con la richiesta iniziale:

  • X-Goog-Upload-Header-Content-Type. Questo è il tipo di contenuti del file che viene caricato e deve essere impostato su application/zip.
  • X-Goog-Upload-Command. Impostata su start
  • X-Goog-Upload-Header-Content-Length. Imposta il numero di byte dei dati di caricamento da trasferire nelle richieste successive. Se la lunghezza non è nota al momento della richiesta, puoi omettere questa intestazione.
  • Content-Type. Questo è il tipo di contenuto dei metadati e deve essere impostato su application/json.
  • Content-Length. Imposta il numero di byte fornito nel corpo di questa richiesta iniziale.
Esempio: richiesta di avvio sessione ripristinabile

L'esempio seguente mostra come avviare una sessione ripristinabile per l'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" }

La sezione successiva descrive come gestire la risposta.

Passaggio 2: salva l'URI della sessione ripristinabile

Se la richiesta di avvio della sessione ha esito positivo, il server API risponde con un codice di stato HTTP 200 OK. Inoltre, fornisce un'intestazione X-Goog-Upload-URL che specifica l'URI della sessione ripristinabile. L'intestazione X-Goog-Upload-URL, mostrata nell'esempio seguente, include un parametro di query upload_id che fornisce l'ID di caricamento univoco da utilizzare per la sessione. La risposta contiene anche un X-Goog-Upload-Status che sarà active se la richiesta di caricamento era valida e accettata. Questo stato potrebbe essere final se il caricamento è stato rifiutato.

Esempio: risposta di avvio della sessione ripristinabile

Ecco la risposta alla richiesta nel passaggio 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

Il valore dell'intestazione X-Goog-Upload-URL, come mostrato nella risposta di esempio precedente, è l'URI della sessione che userai come endpoint HTTP per eseguire l'effettivo caricamento del file o eseguire query sullo stato del caricamento.

Copia e salva l'URI della sessione in modo da poterlo utilizzare per le richieste successive.

Passaggio 3. Carica il file

Per caricare il file, invia una richiesta POST all'URI di caricamento ottenuto in passaggio precedente. Il formato della richiesta di caricamento è:

POST session_uri

Le intestazioni HTTP da utilizzare quando si effettuano le richieste di caricamento di file ripristinabili includono:

  1. Content-Length. Imposta questo elemento sul numero di byte che carichi in questa richiesta, che in genere corrisponde alle dimensioni del file di caricamento.
  2. X-Goog-Upload-Command. Impostalo su upload e finalize.
  3. X-Goog-Upload-Offset. Questo ha specificato l'offset a cui devono essere scritti i byte. Tieni presente che i clienti devono caricare i byte in modo seriale.
Esempio: richiesta di caricamento file ripristinabile

Ecco una richiesta ripristinabile per caricare l'intero file ZIP da 2.000.000 di byte per l'esempio corrente.

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 la richiesta ha esito positivo, il server risponde con un 200 Ok HTTP.

Se la richiesta di caricamento viene interrotta o se ricevi un messaggio 503 Service Unavailable HTTP o un altro altra risposta 5xx dal server, segui la procedura descritta in Riprendi un caricamento interrotto.


Caricamento del file in blocchi

Con i caricamenti ripristinabili, puoi suddividere un file in blocchi e inviare una serie di richieste per caricare ogni blocco in sequenza. Questo non è l'approccio da preferire perché le richieste aggiuntive presentano costi di prestazioni generalmente non necessarie. Consigliamo ai client di caricare tutti i byte rimanenti del payload includi il comando finalize in ogni comando upload.

Tuttavia, potresti dover utilizzare il chunking per ridurre la quantità di dati trasferiti in una singola richiesta. Ti consente inoltre di svolgere operazioni come l'indicazione di indicazioni di avanzamento del caricamento per i browser precedenti che non supportano per impostazione predefinita lo stato di avanzamento del caricamento.


Riprendere un caricamento interrotto

Se una richiesta di caricamento viene interrotta prima di ricevere una risposta o se ricevi un Risposta HTTP 503 Service Unavailable dal server; dovrai riprendere il caricamento interrotto. Per:

  1. Stato della richiesta. Esegui una query sullo stato attuale del caricamento inviando una richiesta all'URI di caricamento con X-Goog-Upload-Command impostato su query.

    Nota: puoi richiedere lo stato tra i blocchi, non solo se il caricamento viene interrotto. Questo è utile, ad esempio, se vuoi mostrare le indicazioni di avanzamento del caricamento per i browser precedenti.

  2. Ottieni il numero di byte caricati. Elabora la risposta della query sullo stato. Il server utilizza l'intestazione X-Goog-Upload-Size-Received nella sua risposta per specificare quanti byte ha ricevuto finora.
  3. Carica i dati rimanenti. Infine, ora che sai dove riprendere la richiesta, invia o il blocco attuale di dati rimanenti. Tieni presente che in entrambi i casi devi trattare i dati rimanenti come un blocco separato, devi impostare l'offset dell'intestazione X-Goog-Upload-Offset con l'offset corretto quando riprendi il caricamento.
Esempio: riprendere un caricamento interrotto

1) Richiedi lo stato del caricamento.

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

Come con tutti i comandi, il client deve verificare l'intestazione X-Goog-Upload-Status nella risposta HTTP di un comando di query. Se l'intestazione è presente e il valore non è active, il caricamento è già stato interrotto.

2) Estrai il numero di byte caricati finora dalla risposta.

La risposta del server utilizza l'intestazione X-Goog-Upload-Size-Received per indicare che ha ricevuto finora i primi 43 byte del file.

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

3) Riprendi il caricamento dal punto in cui è stato interrotto.

La seguente richiesta riprende il caricamento inviando i byte rimanenti del file, a partire dal 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

Best practice

Quando carichi contenuti multimediali, è utile conoscere alcune best practice relative alla gestione degli errori.

  • Riprendi o riprova i caricamenti non riusciti a causa di interruzioni della connessione o di eventuali errori di 5xx, tra cui:
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Utilizza una strategia di backoff esponenziale se viene restituito un errore del server 5xx quando riprendi o ritentano le richieste di caricamento. Questi errori possono verificarsi se un server viene sovraccarico. Il backoff esponenziale può aiutare ad alleviare questo tipo di problemi durante i periodi di volume elevato di richieste o traffico di rete intenso.
  • Altri tipi di richieste non devono essere gestiti dal backoff esponenziale, ma puoi comunque provarne diversi. Quando riprovi a queste richieste, limita il numero di nuovi tentativi. Ad esempio, prima di segnalare un errore, il codice potrebbe limitare a 10 nuovi tentativi.
  • Gestisci 404 Not Found errori quando esegui caricamenti ripristinabili, ricominciando l'intero caricamento dall'inizio.

Backoff esponenziale

Il backoff esponenziale è una strategia di gestione degli errori standard per le applicazioni di rete in cui il client ritenta periodicamente una richiesta non riuscita in un intervallo di tempo sempre più lungo. Se un volume elevato di richieste o un elevato traffico di rete causa la restituzione di errori da parte del server, il backoff esponenziale può essere una buona strategia per gestire questi errori. Al contrario, non si tratta di una strategia pertinente per la gestione di errori non correlati al volume di rete o ai tempi di risposta, quali credenziali di autorizzazione non valide o errori File non trovato.

Se utilizzato correttamente, il backoff esponenziale aumenta l'efficienza dell'utilizzo della larghezza di banda, riduce il numero di richieste necessarie per ottenere una risposta positiva e massimizza la velocità effettiva delle richieste in ambienti simultanei.

Il flusso per l'implementazione del backoff esponenziale semplice è il seguente:

  1. Effettua una richiesta all'API.
  2. Ricevi una risposta HTTP 503, che indica che devi riprovare a eseguire la richiesta.
  3. Attendi 1 secondo + numero_casuale_millisecondi e riprova a eseguire la richiesta.
  4. Ricevi una risposta HTTP 503, che indica che devi riprovare a eseguire la richiesta.
  5. Attendi 2 secondi + numero_casuale_millisecondi e riprova a eseguire la richiesta.
  6. Ricevi una risposta HTTP 503, che indica che devi riprovare a eseguire la richiesta.
  7. Attendi 4 secondi + numero_casuale_millisecondi e riprova a eseguire la richiesta.
  8. Ricevi una risposta HTTP 503, che indica che devi riprovare a eseguire la richiesta.
  9. Attendi 8 secondi + numero_casuale_millisecondi e riprova a eseguire la richiesta.
  10. Ricevi una risposta HTTP 503, che indica che devi riprovare a eseguire la richiesta.
  11. Attendi 16 secondi + numero_casuale_millisecondi e riprova a inviare la richiesta.
  12. Interrompi. Segnala o registra un errore.

Nel flusso precedente, numero_casuale_millisecondi è un numero casuale di millisecondi inferiore o uguale a 1000. Questa operazione è necessaria perché l'introduzione di un piccolo ritardo casuale consente di distribuire il carico in modo più uniforme ed evitare la possibilità di calpestare il server. Il valore di random_number_milliseconds deve essere ridefinito dopo ogni attesa.

Nota : l'attesa è sempre (2 ^ n) + numero_casuale_millisecondi, dove n è un numero intero monotonico crescente inizialmente definito come 0. Il numero intero n viene incrementato di 1 per ogni iterazione (ogni richiesta).

L'algoritmo è impostato per terminare quando n è 5. Questo limite impedisce ai client di riprovare all'infinito e determina un ritardo totale di circa 32 secondi prima che una richiesta venga considerata "un errore irreversibile". È consentito un numero massimo maggiore di nuovi tentativi, soprattutto se è in corso un caricamento di lunga durata. assicurati di limitare il ritardo dei nuovi tentativi a un valore ragionevole, ad esempio inferiore a un minuto.