Créer un package

Options d'importation

L'API Android Over The Air vous permet d'importer des données de package afin de créer une ressource Package. Il s'agit Packages OTA pouvant être associés à une ou plusieurs configurations afin de distribuer la mise à jour aux appareils.

Nous fournissons un binaire pour Linux et Windows afin de faciliter les importations de packages avec reprise que vous sont sans frais à utiliser au lieu de mettre en œuvre les protocoles décrits ci-dessous. Si vous souhaitez en savoir plus veuillez utiliser l'un des protocoles décrits ci-dessous.

Pour l'utiliser, vous devez d'abord créer un compte de service et obtenir un fichier de clé JSON pour ce compte. Veuillez consulter notre guide de création d'un compte.
Une fois que vous disposez du binaire et du fichier de clé, vous pouvez l'exécuter avec des options de ligne de commande pour spécifier le fichier de clé, votre déploiement et le package que vous importez. Veuillez utiliser --help pour voir toutes les options.

Protocoles d'importation

Vous pouvez effectuer des requêtes d'importation via l'une des méthodes exposées ci-dessous. Spécifiez la méthode que vous utilisez avec l'en-tête de requête X-Goog-Upload-Protocol.

  • Importation en plusieurs parties : X-Goog-Upload-Protocol: multipart. Pour transférer rapidement des fichiers et des métadonnées plus petits ; transfère le fichier ainsi que les métadonnées qui le décrivent, le tout dans une seule requête.
  • Importation avec reprise : X-Goog-Upload-Protocol: resumable. Pour un transfert fiable, ce qui est particulièrement important avec . Avec cette méthode, vous utilisez une requête de lancement de session qui peut éventuellement inclure des métadonnées. C'est une bonne stratégie à utiliser pour la plupart applications, car il fonctionne également pour des fichiers plus petits au prix d'une requête HTTP supplémentaire par importation.

Importation en plusieurs parties

C'est un bon choix si les données que vous envoyez sont de petite taille pour le réimporter dans son intégralité en cas d'échec de la connexion.

Pour utiliser l'importation en plusieurs parties, envoyez une requête POST à la commande /upload/package URI et définissez X-Goog-Upload-Protocol sur multipart.

Les en-têtes HTTP de premier niveau à utiliser lors d'une importation en plusieurs parties incluent :

  • Content-Type Défini sur "multipart/related" et inclut la chaîne de délimitation utilise pour identifier les parties de la demande.
  • Content-Length. Défini sur le nombre total d'octets dans le corps de la requête.

Le corps de la requête est mis en forme en tant que contenu multipart/related. type [RFC2387] et contient exactement deux parties. Les parties sont identifiées par une chaîne de délimitation et la dernière chaîne est suivie de deux traits d'union.

Chaque partie de la requête en plusieurs parties nécessite un en-tête Content-Type supplémentaire :

  1. Partie de métadonnées:doit apparaître en premier, et Content-Type doit être application/json.
  2. Partie multimédia:doit apparaître en deuxième, et Content-Type doit être application/zip.

Exemple : Importation en plusieurs parties

L'exemple ci-dessous illustre une requête d'importation en plusieurs parties pour 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--

Si la requête aboutit, le serveur affiche le code d'état HTTP 200 OK.

HTTP/1.1 200

Pour ce faire, vous pouvez utiliser curl et oauth2l. Voici un exemple de requête qui suppose que vous utilisez une clé de service (consultez notre procédure d'autorisation.

Exemple de requête 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
  

Importation avec reprise

Pour importer des fichiers de données de manière plus fiable, vous pouvez utiliser le protocole d'importation avec reprise. Ce protocole permet de reprendre une opération d'importation après un échec de communication ayant interrompu le flux de données. Il est particulièrement utile si vous transférez des fichiers volumineux et que le risque d'interruption du réseau ou un autre échec de transmission est élevé, par exemple lors d'une importation à partir d'une application cliente mobile. Il peut également réduire l'utilisation de la bande passante en cas de défaillance du réseau, car vous n'avez pas à relancer les importations de fichiers volumineux depuis le début.

Le protocole d'importation avec reprise utilise plusieurs commandes:

  1. Démarrez une session avec reprise. Envoyez une requête initiale à l'URI d'importation qui inclut le paramètre et établit un emplacement unique d'importation avec reprise.
  2. Enregistrez l'URI de la session avec reprise. Enregistrez l'URI de la session renvoyé dans le la réponse à la demande initiale ; vous l'utiliserez pour les requêtes restantes dans cette session.
  3. Importez le fichier. Envoyez tout ou partie du fichier ZIP à l'URI de la session avec reprise.

En outre, les applications qui utilisent l'importation avec reprise doivent posséder un code pour reprendre une importation interrompue. Si une importation est interrompue, déterminer la quantité de données reçues, puis reprendre l'importation à partir de ce point.

Remarque : Une URI d'importation expire au bout de trois jours.

Étape 1 : Démarrez une session avec reprise

Pour lancer une importation avec reprise, envoyez une requête POST à /upload/package URI et définissez X-Goog-Upload-Protocol sur resumable.

Pour cette requête de lancement, le corps ne doit contenir que les métadonnées ; vous transférez les véritables du fichier que vous souhaitez importer dans les requêtes ultérieures.

Utilisez les en-têtes HTTP suivants avec la requête initiale :

  • X-Goog-Upload-Header-Content-Type Type de contenu du fichier en cours d'importation. Il doit être défini sur application/zip.
  • X-Goog-Upload-Command Définir sur start
  • X-Goog-Upload-Header-Content-Length. Définissez le nombre d'octets des données d'importation à transférer dans les requêtes ultérieures. Si cette valeur est inconnue au moment de cette requête, vous pouvez omettre cet en-tête.
  • Content-Type Il s'agit du type de contenu des métadonnées. Il doit être défini sur application/json.
  • Content-Length. Définissez le nombre d'octets fournis dans le corps de cette requête initiale.
Exemple : Requête de lancement de session avec reprise

L'exemple suivant montre comment lancer une session avec reprise pour 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 section suivante décrit comment gérer la réponse.

Étape 2 : Enregistrez l'URI de la session avec reprise

Si la requête de lancement de session aboutit, le serveur d'API répond par un code d'état HTTP 200 OK. En outre, il fournit un en-tête X-Goog-Upload-URL qui spécifie votre URI de session avec reprise. L'en-tête X-Goog-Upload-URL, illustré dans l'exemple ci-dessous, inclut un paramètre de requête upload_id. qui donne l'ID d'importation unique à utiliser pour cette session. La réponse contient également un X-Goog-Upload-Status qui sera active si la requête d'importation était valide et acceptée. Cet état peut être final si l'importation a été refusée.

Exemple : Réponse de lancement de session avec reprise

La réponse à la requête de l'étape 1 se présente comme suit :

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

La valeur de l'en-tête X-Goog-Upload-URL, comme indiqué dans l'exemple de réponse ci-dessus, est l'URI de session que vous utiliserez comme point de terminaison HTTP pour effectuer l'importation réelle du fichier ou interroger l'état de l'importation.

Copiez et enregistrez l'URI de la session afin de pouvoir l'utiliser pour les requêtes ultérieures.

Étape 3 : Importez le fichier

Pour importer le fichier, envoyez une requête POST à l'URI d'importation obtenu dans la à l'étape précédente. Le format de la requête d'importation se présente comme suit :

POST session_uri

Les en-têtes HTTP à utiliser lors des requêtes d'importation de fichiers avec reprise incluent:

  1. Content-Length Définissez ce paramètre sur le nombre d'octets que vous importez dans cette requête, qui correspond généralement à la taille du fichier d'importation.
  2. X-Goog-Upload-Command Définissez cette valeur sur upload et finalize.
  3. X-Goog-Upload-Offset Indique le décalage auquel les octets doivent être écrits. Notez que les clients doit importer des octets en série.
Exemple : Requête d'importation de fichier avec reprise

Voici une requête avec reprise permettant d'importer l'intégralité du fichier ZIP de 2 000 000 octets pour l'exemple actuel.

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

Si la requête aboutit, le serveur envoie une réponse HTTP 200 Ok.

Si la requête d'importation est interrompue ou si vous recevez un appel HTTP 503 Service Unavailable ou une autre réponse 5xx du serveur, suivez la procédure décrite dans la section Reprendre une importation interrompue.


Importer un fichier fragmenté

Les importations avec reprise vous permettent de diviser un fichier en plusieurs fragments et d'envoyer une série de requêtes afin d'importer chacun de ces fragments l'un après l'autre. Ce n'est pas l'approche privilégiée, car les requêtes supplémentaires entraînent des coûts de performances. qui ne sont généralement pas nécessaires. Nous recommandons aux clients de télécharger tous les octets restants de la charge utile et incluez la commande finalize dans chaque commande upload.

Cependant, vous devrez peut-être recourir à la fragmentation pour réduire la quantité de données transférées demande simple. Il vous permet, entre autres, d'indiquer la progression de l'importation pour les anciens navigateurs. qui ne sont pas compatibles par défaut avec la progression de l'importation.


Reprendre une importation interrompue

Si une demande d'importation est interrompue avant de recevoir une réponse ou si vous recevez une HTTP 503 Service Unavailable du serveur, vous devez alors reprendre l'importation interrompue. Pour ce faire :

  1. Interrogez l'état. Interrogez l'état actuel de l'importation en envoyant une requête à l'URI d'importation. avec X-Goog-Upload-Command défini sur query.

    Remarque : Vous pouvez interroger l'état entre les fragments, et pas seulement si l'importation est interrompue. C'est Cela peut être utile, par exemple, si vous souhaitez afficher les indications de progression de l'importation pour les anciens navigateurs.

  2. Obtenez le nombre d'octets importés. Traitez la réponse à partir de la requête d'état. Le serveur utilise l'en-tête X-Goog-Upload-Size-Received dans sa réponse pour spécifier le nombre d'octets reçus jusqu'à présent.
  3. Importez les données restantes. Enfin, maintenant que vous savez où reprendre la requête, envoyez le les données restantes ou le fragment actuel. Notez que vous devez traiter les données restantes comme un fragment séparé dans les deux cas, donc vous devez définir l'en-tête X-Goog-Upload-Offset avec le décalage approprié lorsque vous reprenez l'importation.
Exemple : Reprendre une importation interrompue

1) Interrogez l'état de l'importation.

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

Comme pour toutes les commandes, le client doit vérifier l'en-tête X-Goog-Upload-Status dans la réponse HTTP d'une commande de requête. Si l'en-tête est présent et que la valeur n'est pas active, cela signifie que l'importation a déjà été arrêtée.

2) Procédez à l'extraction du nombre d'octets importés jusqu'à présent à partir de la réponse.

La réponse du serveur utilise l'en-tête X-Goog-Upload-Size-Received pour indiquer qu'il a reçu les 43 premiers octets du fichier jusqu’à présent.

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

3) Reprenez l'importation là où elle s'était arrêtée.

La requête suivante reprend l'importation en envoyant les octets restants du fichier, en commençant par l'octet 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

Bonnes pratiques

En ce qui concerne l'importation de médias, il est utile de connaître certaines bonnes pratiques en matière de traitement des erreurs.

  • Reprenez ou relancez les importations qui échouent en raison d'interruptions de connexion ou d'erreurs 5xx, parmi lesquelles :
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Si une erreur de serveur 5xx est renvoyée lors de la reprise ou de la nouvelle tentative d'importation, utilisez une stratégie d'intervalle exponentiel entre les tentatives. Ces erreurs peuvent se produire quand un serveur est surchargé. L'intervalle exponentiel entre les tentatives peut aider à résoudre ce type de problème lors des pics de volumes de requêtes ou de trafic réseau.
  • Les autres types de requêtes ne doivent pas être gérés par un intervalle exponentiel entre les tentatives, mais vous pouvez toujours en relancer un certain nombre. Lorsque vous relancez ces requêtes, limitez le nombre de tentatives. Par exemple, votre code peut limiter à 10 tentatives ou moins avant de signaler une erreur.
  • Traitez les erreurs 404 Not Found lorsque vous effectuez des importations avec reprise en recommençant l'importation depuis le début.

Intervalle exponentiel entre les tentatives

L'intervalle exponentiel entre les tentatives est une stratégie standard en matière de traitement d'erreurs pour les applications réseau, selon laquelle le client relance périodiquement une requête ayant échoué sur une durée de plus en plus longue. Si un volume élevé de requêtes ou un trafic réseau important provoquent des erreurs sur le serveur, l'intervalle exponentiel entre les tentatives peut s'imposer comme une stratégie efficace pour traiter ces erreurs. À l'inverse, cette stratégie n'est pas pertinente pour traiter les erreurs sans rapport avec le volume réseau ou les temps de réponse, telles que les erreurs associées aux identifiants d'autorisation non valides ou aux fichiers introuvables.

Utilisé correctement, l'intervalle exponentiel entre les tentatives augmente l'efficacité de l'utilisation de la bande passante, réduit le nombre de requêtes nécessaires pour obtenir une réponse positive et optimise le débit des requêtes dans les environnements avec simultanéité.

Le fonctionnement de l'intervalle exponentiel simple entre les tentatives se présente comme suit :

  1. Vous envoyez une requête à l'API.
  2. Vous recevez une réponse HTTP 503, qui indique que vous devez relancer la requête.
  3. Vous patientez 1 seconde + "random_number_milliseconds", puis vous relancez la requête.
  4. Vous recevez une réponse HTTP 503, qui indique que vous devez relancer la requête.
  5. Vous patientez 2 secondes + "random_number_milliseconds", puis vous relancez la requête.
  6. Vous recevez une réponse HTTP 503, qui indique que vous devez relancer la requête.
  7. Vous patientez 4 secondes + "random_number_milliseconds", puis vous relancez la requête.
  8. Vous recevez une réponse HTTP 503, qui indique que vous devez relancer la requête.
  9. Vous patientez 8 secondes + "random_number_milliseconds", puis vous relancez la requête.
  10. Vous recevez une réponse HTTP 503, qui indique que vous devez relancer la requête.
  11. Vous patientez 16 secondes + "random_number_milliseconds", puis vous relancez la requête.
  12. Vous arrêtez, puis vous signalez ou consignez une erreur.

Dans le flux ci-dessus, "random_number_milliseconds" correspond à un nombre aléatoire de millisecondes inférieur ou égal à 1 000. Cette étape est nécessaire, car l'introduction d'un petit délai aléatoire permet de répartir la charge de manière plus uniforme et d'éviter l'embase du serveur. La valeur de "random_number_milliseconds" doit être redéfinie après chaque temps d'attente.

Remarque : L'attente correspond toujours à (2 ^ n) + "random_number_milliseconds", où "n" est un entier augmentant de manière monotone défini initialement sur 0. L'entier "n" est augmenté de 1 pour chaque itération (chaque requête).

L'algorithme est configuré pour se terminer lorsque "n" vaut 5. Ce plafond empêche les clients d'effectuer des relances indéfiniment et entraîne un délai total d'environ 32 secondes avant qu'une requête ne soit considérée comme une "erreur non récupérable". Vous pouvez tout à fait définir un nombre maximal de tentatives plus élevé, surtout si une longue importation est en cours d'exécution. Veillez simplement à limiter le délai des nouvelles tentatives de manière raisonnable, par exemple à moins d'une minute.