Crear un paquete

Opciones de carga

La API de Android Over The Air te permite subir datos de paquetes para crear un nuevo recurso de paquete. Son Son paquetes inalámbricos que pueden asociarse con una o más configuraciones para que se entregue la actualización. a los dispositivos.

Ofrecemos un objeto binario para Linux y Windows para facilitar las cargas de paquetes reanudables que tú son de uso libre en vez de implementar los protocolos que se describen a continuación. Si deseas una introducción más profunda para la integración, usa uno de los protocolos que se describen a continuación.

Para usarla, primero debes crear una cuenta de servicio y obtener un archivo de claves JSON para ella. Consulta nuestra guía para crear la cuenta aquí.
Una vez que tengas el archivo binario y el archivo de claves, puedes ejecutarlo con opciones de línea de comandos para especificar el archivo de claves, la implementación y el paquete que subirás. Usa --help para ver todas las opciones.

Protocolos de carga

Puedes realizar solicitudes de carga de cualquiera de las siguientes formas. Especifica el método que usas con el encabezado de solicitud X-Goog-Upload-Protocol.

  • Carga multiparte: X-Goog-Upload-Protocol: multipart. Para una transferencia rápida de archivos y metadatos más pequeños; transfiere el archivo junto con metadatos que lo describen, todo en una sola solicitud.
  • Carga reanudable: X-Goog-Upload-Protocol: resumable. Para una transferencia confiable, es importante en particular para archivos. Con este método, utilizas una solicitud de inicio de sesión, que puede incluir metadatos. Esta es una buena estrategia para la mayoría porque también funciona para archivos más pequeños al costo de una solicitud HTTP adicional por carga.

Carga multiparte

Esta es una buena opción si los datos que vas a enviar son pequeños suficiente para volver a subirlo por completo si falla la conexión.

Para usar una carga multiparte, realiza una solicitud POST a /upload/package. y establece X-Goog-Upload-Protocol en multipart.

Entre los encabezados HTTP de nivel superior que se deben usar cuando se realiza una solicitud de carga multiparte, se incluyen los siguientes:

  • Content-Type Configurada como multiparte/relacionada e incluye la cadena de límite que que se usa para identificar las partes de la solicitud.
  • Content-Length. Configurado como la cantidad total de bytes en el cuerpo de la solicitud.

El cuerpo de la solicitud tiene el formato de contenido multipart/related el tipo [RFC2387] y contiene exactamente dos partes. Las partes se identifican mediante una string de límite, y la última string de límite está seguida por dos guiones.

Cada parte de la solicitud multiparte necesita un encabezado Content-Type adicional:

  1. Parte de metadatos: Debe ir primero, y Content-Type debe ser application/json.
  2. Parte de contenido multimedia: debe ir en segundo lugar, y Content-Type debe ser application/zip.

Ejemplo: Carga multiparte

En el siguiente ejemplo, se muestra una solicitud de carga multiparte para la API de 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 solicitud se realiza correctamente, el servidor muestra el código de estado HTTP 200 OK.

HTTP/1.1 200

Una forma de lograr esto fácilmente es usar curl. y oauth2l. A continuación, se incluye un ejemplo de solicitud que supone que usas una clave de servicio (consulta nuestra Cómo autorizarse para obtener más información).

Solicitud cURL de ejemplo
    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
  

Carga reanudable

Para cargar archivos de datos de manera más confiable, puedes usar el protocolo de carga reanudable. Este protocolo permite te permite reanudar una operación de carga después de que una falla de comunicación haya interrumpido el flujo de datos. Integra es especialmente útil si estás transfiriendo archivos grandes y ante la probabilidad de que se produzca una interrupción en la red. o algún otro error de transmisión es alto, por ejemplo, cuando subes datos desde una app cliente desde un dispositivo móvil. Integra También puedes reducir el uso de ancho de banda en caso de fallas en la red, ya que no tienes que reiniciar las cargas de archivos grandes desde el principio.

En el protocolo de carga reanudable, se usan varios comandos:

  1. Inicia una sesión reanudable. Realiza una solicitud inicial al URI de carga que incluya el metadatos y establece una ubicación única de carga reanudable.
  2. Guarda eI URI de la sesión reanudable. Guarda el URI de la sesión que se muestra en el respuesta de la solicitud inicial; lo usarás para las solicitudes restantes de esta sesión.
  3. Sube el archivo. Envía todo el archivo ZIP o parte de él al URI de la sesión reanudable.

Además, las aplicaciones que usan carga reanudable deben tener un código para reanudar una carga interrumpida. Si una carga es interrumpir, averiguar cuántos datos se recibieron correctamente y, luego, reanudar la carga desde ese punto.

Nota: Los URIs de carga vencen después de 3 días.

Paso 1: Inicia una sesión reanudable

Para iniciar una carga reanudable, realiza una solicitud POST al elemento /upload/package. y establece X-Goog-Upload-Protocol en resumable.

Para esta solicitud de inicio, el cuerpo debe contener solo los metadatos; transferirás la capacidad el contenido del archivo que desees subir en solicitudes posteriores.

Usa los siguientes encabezados HTTP con la solicitud inicial:

  • X-Goog-Upload-Header-Content-Type Este es el tipo de contenido del archivo que se está subiendo y se debe configurar como application/zip.
  • X-Goog-Upload-Command Establecer en start
  • X-Goog-Upload-Header-Content-Length. Configurado como la cantidad de bytes de datos de carga que se transferirán en solicitudes posteriores. Si no se conoce la longitud en el momento de esta solicitud, puedes omitir este encabezado.
  • Content-Type Este es el tipo de contenido de los metadatos y debe configurarse como application/json.
  • Content-Length. Configurado como la cantidad de bytes que se proporcionaron en el cuerpo de esta solicitud inicial.
Ejemplo: Solicitud de inicio de sesión reanudable

En el siguiente ejemplo, se muestra cómo iniciar una sesión reanudable para la API de 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" }

En la próxima sección, se describe cómo manejar la respuesta.

Paso 2: Guarda el URI de la sesión reanudable

Si la solicitud de inicio de sesión se realiza correctamente, el servidor de la API responde con un código de estado HTTP 200 OK. Además, proporciona un encabezado X-Goog-Upload-URL que especifica el URI de la sesión reanudable. El encabezado X-Goog-Upload-URL, que se muestra en el siguiente ejemplo, incluye un parámetro de consulta upload_id que proporciona el ID de carga único para usar en esta sesión. La respuesta también contiene un X-Goog-Upload-Status encabezado, que tendrá un valor de active si la solicitud de carga es válida y se aceptó. Este estado puede ser final si se rechazó la carga.

Ejemplo: Respuesta de inicio de sesión reanudable

A continuación, se muestra la respuesta a la solicitud presentada en el paso 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

El valor del encabezado X-Goog-Upload-URL, como se muestra en la respuesta de ejemplo anterior, es el URI de sesión que usarás como extremo HTTP para subir el archivo o consultar el estado de carga.

Copia y guarda este URI de sesión para poder usarlo en solicitudes posteriores.

Paso 3: Sube el archivo

Para subir el archivo, envía una solicitud POST al URI de carga que obtuviste en el paso anterior. El formato de la solicitud de carga es el siguiente:

POST session_uri

Entre los encabezados HTTP que se deben usar cuando se realizan solicitudes de carga de archivos reanudables, se incluyen los siguientes:

  1. Content-Length Configura esta opción como la cantidad de bytes que subirás en esta solicitud, que suele ser el tamaño del archivo que se carga.
  2. X-Goog-Upload-Command Establece esto en upload y finalize.
  3. X-Goog-Upload-Offset Esto especificó el desplazamiento en el que se deben escribir los bytes. Ten en cuenta que los clientes debe subir bytes en serie.
Ejemplo: Solicitud de carga de archivo reanudable

A continuación, se muestra una solicitud reanudable para subir el archivo ZIP completo de 2,000,000 bytes del ejemplo actual.

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 solicitud se realiza correctamente, el servidor responde con una 200 Ok HTTP.

Si se interrumpe la solicitud de carga, o si recibes un 503 Service Unavailable HTTP o cualquier 5xx del servidor, sigue el procedimiento que se describe en la sección para reanudar una carga interrumpida.


Sube el archivo en partes

Con las cargas reanudables, puedes fragmentar un archivo y enviar diferentes solicitudes para cargar cada parte en secuencia. No se recomienda este enfoque, ya que las solicitudes adicionales tienen costos de rendimiento asociados y, por lo general, no es necesario. Recomendamos que los clientes suban todos los bytes restantes de la carga útil y incluir el comando finalize con cada comando upload.

Sin embargo, es posible que necesites usar la fragmentación para reducir la cantidad de datos que se transfieren en en una sola solicitud. También te permite realizar acciones como proporcionar indicaciones de progreso de carga en los navegadores heredados que no tienen compatibilidad con el progreso de carga de forma predeterminada.


Reanuda una carga interrumpida

Si una solicitud de carga se interrumpe antes de que recibas una respuesta o si recibes una respuesta HTTP 503 Service Unavailable del servidor, debes reanudar la carga interrumpida. Para ello, sigue estos pasos:

  1. Estado de la solicitud. Envía una solicitud al URI de carga para consultar el estado actual de la carga con el X-Goog-Upload-Command configurado como query.

    Nota: Puedes solicitar el estado entre partes, no solo si se interrumpe la carga. Este es útil, por ejemplo, si quieres mostrar indicaciones de progreso de carga en navegadores heredados.

  2. Obtén la cantidad de bytes cargados. Procesa la respuesta de la consulta de estado. El servidor usa el encabezado X-Goog-Upload-Size-Received en su respuesta para especificar cuántos bytes recibió hasta el momento.
  3. Sube los datos restantes. Por último, ahora que sabes dónde reanudar la solicitud, envía el los datos restantes o el fragmento actual. Ten en cuenta que, en cualquiera de los casos, debes tratar los datos restantes como fragmentos separados, Debes configurar el encabezado X-Goog-Upload-Offset con el desplazamiento adecuado cuando reanudes la carga.
Ejemplo: Reanuda una carga interrumpida

1) Solicita el estado de la carga.

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

Al igual que con todos los comandos, el cliente debe verificar el encabezado X-Goog-Upload-Status en la respuesta HTTP de un comando de consulta. Si el encabezado está presente y el valor no es active, significa que ya se cerró la carga.

2) Extrae de la respuesta la cantidad de bytes cargados hasta el momento.

La respuesta del servidor usa el encabezado X-Goog-Upload-Size-Received para indicar que tiene los primeros 43 bytes del archivo hasta ahora.

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

3) Reanuda la carga desde el punto en que se detuvo.

La siguiente solicitud reanuda la carga; para ello, envía los bytes restantes del archivo a partir del 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ácticas recomendadas

Cuando cargues contenido multimedia, es útil conocer algunas de las prácticas recomendadas relacionadas con el manejo de errores:

  • Reanuda o reintenta cargas que no se realizaron de forma correcta debido a interrupciones en la conexión o cualquier error 5xx, incluidos los siguientes:
    • 500 Internal Server Error
    • 502 Bad Gateway
    • 503 Service Unavailable
    • 504 Gateway Timeout
  • Usa una estrategia de retirada exponencial si se muestra cualquier error de servidor 5xx cuando reanudas o reintentas solicitudes de carga. Estos errores pueden ocurrir si un servidor se está sobrecargando. La retirada exponencial puede ayudarte a aliviar este tipo de problemas durante períodos de gran volumen de solicitudes o de tráfico de red intenso.
  • No se deben manejar otros tipos de solicitudes mediante retirada exponencial, pero igual puedes reintentar varias de ellas. Cuando reintentes estas solicitudes, limita la cantidad de veces que lo haces. Por ejemplo, tu código podría limitarse a 10 reintentos o menos antes de informar un error.
  • Maneja los errores 404 Not Found cuando realices cargas reanudables. Para ello, vuelve a iniciar toda la carga desde el comienzo.

Retirada exponencial

La retirada exponencial es una estrategia estándar de manejo de errores para aplicaciones de red en la que el cliente reintenta de forma periódica una solicitud con errores durante un período creciente. Si el servidor presenta errores debido a un gran volumen de solicitudes o tráfico de red, la retirada exponencial puede ser una buena estrategia para manejar estos errores. Por el contrario, esta estrategia no se recomienda para lidiar con errores que no estén relacionados con el volumen de la red o los tiempos de respuesta, como credenciales de autorización no válidas o errores de archivos no encontrados.

Si se la utiliza de forma correcta, la retirada exponencial aumenta la eficiencia del uso del ancho de banda, reduce la cantidad de solicitudes que se requieren para obtener una respuesta correcta y maximiza la capacidad de procesamiento de las solicitudes en entornos simultáneos.

A continuación, se muestra el flujo para implementar una retirada exponencial simple:

  1. Realizar una solicitud a la API
  2. Recibir una respuesta HTTP 503, que indica que debes reintentar la solicitud
  3. Esperar 1 segundo + random_number_milliseconds y reintentar la solicitud
  4. Recibir una respuesta HTTP 503, que indica que debes reintentar la solicitud
  5. Esperar 2 segundos + random_number_milliseconds y reintentar la solicitud
  6. Recibir una respuesta HTTP 503, que indica que debes reintentar la solicitud
  7. Esperar 4 segundos + random_number_milliseconds y reintentar la solicitud
  8. Recibir una respuesta HTTP 503, que indica que debes reintentar la solicitud
  9. Esperar 8 segundos + random_number_milliseconds y reintentar la solicitud
  10. Recibir una respuesta HTTP 503, que indica que debes reintentar la solicitud
  11. Esperar 16 segundos + random_number_milliseconds y reintentar la solicitud
  12. Detener; Informar o registrar un error

En el flujo anterior, random_number_milliseconds es una cantidad aleatoria de milisegundos menor o igual que 1,000. Esto es necesario, ya que agregar un pequeño retraso aleatorio ayuda a distribuir la carga de manera más uniforme y a evitar la posibilidad de fallas en cascada en el servidor. El valor de random_number_milliseconds se debe volver a definir tras cada espera.

Nota: La espera siempre es (2 ^ n) + random_number_milliseconds, en la que n es un número entero, que crece de forma monotónica, definido en un inicio como 0. El número entero n aumenta de a 1 por cada iteración (cada solicitud).

El algoritmo está configurado para terminar cuando n sea 5. Este límite impide que los clientes reintenten las solicitudes de forma infinita y genera una demora total de alrededor de 32 segundos antes de que una solicitud se considere “un error irrecuperable”. Un límite de reintentos mayor es aceptable, sobre todo si hay una carga larga en progreso. Solo asegúrate de limitar la demora de reintentos a un valor razonable, por ejemplo, menos de un minuto.