Compatibilidad con actualizaciones de la app (nativas)

En esta guía, se describe cómo admitir actualizaciones integradas en tu app mediante código nativo (C o C++). Existen guías separadas para casos en los que tu implementación usa los lenguajes de programación Kotlin o Java, y casos en los que esta usa Unity.

Descripción general del SDK nativo

El SDK nativo de Play Core forma parte de la familia del SDK de Play Core. El SDK nativo incluye un archivo de encabezado C, app_update.h, que une AppUpdateManager del SDK de Java Play Core. Este archivo de encabezado permite que tu app llame a la API para realizar actualizaciones integradas en la app directamente desde tu código nativo.

Cómo configurar tu entorno de desarrollo

A fin de configurar tu entorno de desarrollo, sigue las instrucciones de configuración en la sección de código nativo de la guía de la biblioteca de Play Core.

Después de integrar el SDK nativo de Play Core en tu proyecto, incluye la siguiente línea en los archivos que contengan llamadas a la API:

#include "play/app_update.h"

Cómo inicializar la API de actualizaciones integradas en la app

Siempre que uses la API de actualizaciones en la app, debes llamar a la función AppUpdateManager_init() para inicializarla, como se muestra en el siguiente ejemplo compilado con android_native_app_glue.h:

void android_main(android_app* app) {
  app->onInputEvent = HandleInputEvent;

  AppUpdateErrorCode error_code =
    AppUpdateManager_init(app->activity->vm, app->activity->clazz);
  if (error_code == APP_UPDATE_NO_ERROR) {
    // You can use the API.
  }
}

Cómo comprobar la disponibilidad de actualizaciones

Antes de solicitar una actualización, verifica si hay alguna disponible para tu app. AppUpdateManager_requestInfo() inicia una solicitud asíncrona que recopila la información necesaria para iniciar el flujo de actualización integrada en la app más adelante. Esta función muestra APP_UPDATE_NO_ERROR si la solicitud se inicia correctamente.

AppUpdateErrorCode error_code = AppUpdateManager_requestInfo()

if (error_code == APP_UPDATE_NO_ERROR) {
    // The request has successfully started, check the result using
    // AppUpdateManager_getInfo.
}

Puedes realizar un seguimiento del proceso en curso y el resultado de la solicitud mediante AppUpdateManager_getInfo(). Además del código de error, esta función muestra una estructura opaca AppUpdateInfo, que puedes usar para recuperar información sobre la solicitud de actualización. Por ejemplo, es posible que desees llamar a esta función en cada bucle de juego hasta que muestre un resultado de info no nulo:

AppUpdateInfo* info;
GameUpdate() {

   // Keep calling this in every game loop until info != nullptr
   AppUpdateErrorCode error_code = AppUpdateManager_getInfo(&info);

   if (error_code == APP_UPDATE_NO_ERROR && info != nullptr) {
       // Successfully started, check the result in the following functions
   }
...
}

Cómo verificar la obsolescencia de las actualizaciones

Además de comprobar si hay actualizaciones disponibles, te recomendamos que verifiques cuánto tiempo pasó desde que el usuario recibió una notificación sobre una actualización a través de Google Play Store. Esto puede ayudarte a decidir si debes iniciar una actualización flexible o una actualización inmediata. Por ejemplo, podrías esperar unos días antes de notificar al usuario con una actualización flexible y, luego, solicitar una actualización inmediata.

Usa AppUpdateInfo_getClientVersionStalenessDays() para verificar cuántos días pasaron desde que apareció la actualización en Play Store:

int32_t staleness_days = AppUpdateInfo_getClientVersionStalenessDays(info);

Cómo verificar la prioridad de las actualizaciones

La API de Google Play Developer te permite establecer la prioridad de cada actualización. De esta manera, tu app puede determinar la insistencia con la que recomendará una actualización al usuario. Por ejemplo, considera la siguiente estrategia para establecer la prioridad de las actualizaciones:

  • Mejoras menores en la IU: Actualización de baja prioridad. No solicites una actualización flexible ni una actualización inmediata. Actualiza la app solo cuando el usuario no esté interactuando con ella.
  • Mejoras en el rendimiento: Actualización de prioridad media. Solicita una actualización flexible.
  • Actualización crítica de seguridad: actualización de prioridad alta. Requiere una actualización inmediata.

Para determinar la prioridad, Google Play usa un valor entero entre 0 y 5, en el que 0 es la prioridad predeterminada y 5 es la más alta. A fin de establecer la prioridad de una actualización, usa el campo inAppUpdatePriority en Edits.tracks.releases de la API de Google Play Developer. Se considerará que todas las versiones agregadas en la original tendrán establecida la misma prioridad que este última. Solo se puede establecer la prioridad al momento de lanzar una versión nueva; no se puede cambiar más tarde.

Establece la prioridad mediante la API de Google Play Developer como se describe en la documentación de la API de Play Developer. Especifica la prioridad de actualización de la app en el recurso Edit.tracks pasado en el método Edit.tracks: update. En el siguiente ejemplo, se muestra cómo lanzar una app con código de versión 88 y inAppUpdatePriority 5:

{
  "releases": [{
      "versionCodes": ["88"],
      "inAppUpdatePriority": 5,
      "status": "completed"
  }]
}

En el código de tu app, puedes verificar el nivel de prioridad de una actualización determinada con AppUpdateInfo_getPriority():

int32_t priority = AppUpdateInfo_getPriority(info);

Cómo iniciar una actualización

Después de confirmar que hay una actualización disponible, puedes solicitarla con AppUpdateManager_requestStartUpdate(): Antes de hacerlo, obtén un objeto AppUpdateInfo actualizado y crea un objeto AppUpdateOptions para configurar el flujo de la actualización. Un objeto AppUpdateOptions define opciones para un flujo de actualización integrada en la app, que incluye si la actualización debe ser flexible o inmediata.

En el siguiente ejemplo, se crea un objeto AppUpdateOptions para un flujo de actualización flexible:

// Creates an AppUpdateOptions configuring a flexible in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_FLEXIBLE, &options);

En el siguiente ejemplo, se crea un objeto AppUpdateOptions para un flujo de actualización inmediato:

// Creates an AppUpdateOptions configuring an immediate in-app update flow.
AppUpdateOptions* options;
AppUpdateErrorCode error_code = AppUpdateOptions_createOptions(APP_UPDATE_TYPE_IMMEDIATE, &options);

El objeto AppUpdateOptions también contiene un campo AllowAssetPackDeletion que define si la actualización puede borrar paquetes de recursos si el almacenamiento del dispositivo es limitado. Este campo se establece en false de forma predeterminada, pero puedes usar el método AppUpdateOptions_setAssetPackDeletionAllowed() para establecerlo en true en su lugar:

bool allow = true;
AppUpdateErrorCode error_code = AppUpdateOptions_setAssetPackDeletionAllowed(options, allow);

Una vez que tengas un objeto AppUpdateInfo actualizado y un objeto AppUpdateOptions configurado correctamente, llama a AppUpdateManager_requestStartUpdate() a fin de solicitar de forma asíncrona un flujo de actualización y pasa una actividad de Android jobject para el parámetro final.

AppUpdateErrorCode request_error_code =
AppUpdateManager_requestStartUpdate(info, options, app->activity->clazz);

Para despejar recursos, libera instancias de AppUpdateInfo y AppUpdateOptions que ya no necesites mediante llamadas a AppUpdateInfo_destroy() y AppUpdateOptions_destroy(), respectivamente.

AppUpdateInfo_destroy(info);
AppUpdateOptions_destroy(options);

Para obtener un flujo de actualización inmediata, Google Play muestra una página de confirmación del usuario. Cuando el usuario acepta la solicitud, Google Play descarga e instala automáticamente la actualización en primer plano y, luego, reinicia la app a la versión actualizada si la instalación se realizó correctamente.

Para obtener un flujo de actualización flexible, puedes seguir solicitando objetos AppUpdateInfo actualizados y hacer un seguimiento del estado actual de la actualización mientras el usuario interactúa con la app. Una vez que la descarga finalice correctamente, debes llamar a AppUpdateManager_requestCompleteUpdate() y activar la finalización, como se muestra en el siguiente ejemplo:

AppUpdateStatus status = AppUpdateInfo_getStatus(info);
if (status == APP_UPDATE_DOWNLOADED) {
    AppUpdateErrorCode error_code = AppUpdateManager_requestCompleteUpdate();
    if (error_code != APP_UPDATE_NO_ERROR)
    {
      // There was an error while completing the update flow.
    }
}

Llama a la función AppUpdateManager_destroy() una vez que tu app haya terminado de usar la API a fin de liberar recursos.

Administración de errores

En esta sección, se detallan soluciones de errores comunes indicados con valores específicos de AppUpdateErrorCode:

  • Un código de error de -110, APP_UPDATE_INITIALIZATION_NEEDED indica que la API no se inicializó correctamente. Llama a AppUpdateManager_init() para inicializarla.
  • Un código de error de -4, APP_UPDATE_INVALID_REQUEST indica que algunos parámetros de la solicitud de flujo de actualización presentan errores de formato. Comprueba que los objetos AppUpdateInfo y AppUpdateOptions no sean nulos y tengan el formato correcto.
  • Un código de error de -5, APP_UPDATE_UNAVAILABLE indica que no hay una actualización aplicable disponible. Asegúrate de que la versión de destino tenga el mismo nombre de paquete, ID de aplicación y clave de firma. Si hay una actualización disponible, borra la caché de la app y vuelve a llamar a AppUpdateManager_requestAppUpdateInfo() para actualizar AppUpdateInfo.
  • Un código de error de -6, APP_UPDATE_NOT_ALLOWED indica que no se permite el tipo de actualización indicado por el objeto AppUpdateOption. Comprueba que el objeto AppUpdateInfo indique que el tipo de actualización está permitido antes de iniciar el flujo correspondiente.

Próximos pasos

Prueba las actualizaciones integradas en la app a fin de verificar que la integración funcione correctamente.