Cómo integrar Asset Delivery (código nativo)

Sigue los pasos que se indican en esta guía para acceder a los paquetes de elementos de tu app desde código de C y C++.

El código de integración de ejemplo está disponible en GitHub.

Crea contenido nativo

Usa los siguientes pasos para compilar Play Asset Delivery en el Android App Bundle de tu proyecto. No es necesario que uses Android Studio para seguir estos pasos.

  1. Actualiza la versión del complemento de Android para Gradle en el archivo build.gradle de tu proyecto a 4.0.0 o a una versión posterior.

  2. En el directorio de nivel superior de tu proyecto, crea un directorio para el paquete de elementos. Se usa el nombre de ese directorio como el nombre del paquete de elementos. Los nombres de los paquetes de elementos deben comenzar con una letra y solo pueden contener letras, números y guiones bajos.

  3. En el directorio del paquete de recursos, crea un archivo build.gradle y agrega el siguiente código. Asegúrate de especificar el nombre del paquete de elementos y solo un tipo de entrega:

    // In the asset pack’s build.gradle file:
    plugins {
        id 'com.android.asset-pack'
    }
    
    assetPack {
        packName = "asset-pack-name" // Directory name for the asset pack
        dynamicDelivery {
            deliveryType = "[ install-time | fast-follow | on-demand ]"
        }
    }
    
  4. En el archivo build.gradle de la app del proyecto, agrega el nombre de cada paquete de elementos de tu proyecto, como se muestra a continuación:

    // In the app build.gradle file:
    android {
        ...
        assetPacks = [":asset-pack-name", ":asset-pack2-name"]
    }
    
  5. En el archivo settings.gradle del proyecto, incluye todos los paquetes de elementos de tu proyecto, como se muestra a continuación:

    // In the settings.gradle file:
    include ':app'
    include ':asset-pack-name'
    include ':asset-pack2-name'
    
  6. En el directorio del paquete de elementos, crea el siguiente subdirectorio: src/main/assets.

  7. Coloca los recursos en el directorio src/main/assets. Aquí también puedes crear subdirectorios. Ahora la estructura del directorio de tu app debería verse de la siguiente manera:

    • build.gradle
    • settings.gradle
    • app/
    • asset-pack-name/build.gradle
    • asset-pack-name/src/main/assets/your-asset-directories
  8. Compila el Android App Bundle con Gradle. En el paquete de aplicación que se generó, el directorio raíz ahora incluye lo siguiente:

    • asset-pack-name/manifest/AndroidManifest.xml: configura el identificador y el modo de entrega del paquete de elementos.
    • asset-pack-name/assets/your-asset-directories: es el directorio que contiene todos los elementos entregados como parte del paquete de elementos.

    Gradle genera el manifiesto para cada paquete de recursos y te proporciona el directorio assets/.

  9. Opcional: Configura el paquete de aplicación para que sea compatible con diferentes formatos de compresión de texturas.

Cómo realizar la integración con la biblioteca de Play Asset Delivery

Debes implementar esta API según el tipo de entrega del paquete de recursos al que deseas acceder. Estos pasos se muestran en el siguiente diagrama de flujo.

Diagrama de flujo del paquete de elementos para el código nativo

Figura 1: Diagrama de flujo para acceder a paquetes de recursos

El SDK nativo de Play Core proporciona el archivo de encabezado de C de play/asset_pack.h para solicitar paquetes de recursos, administrar descargas y acceder a los recursos.

Cómo configurar tu entorno de desarrollo para el SDK nativo de Play Core

Descargar Play Core Native SDK

Antes de iniciar la descarga, debes aceptar los siguientes términos y condiciones.

Términos y Condiciones

Última modificación: 24 de septiembre de 2020
  1. Si usas el kit de desarrollo de software de Play Core, aceptas estas condiciones, además de las Condiciones del Servicio de las APIs de Google ("Condiciones del Servicio de las APIs"). Si se encuentran en conflicto, estas tendrán prioridad sobre las Condiciones del Servicio de las APIs. Lee estas condiciones y las Condiciones del Servicio de la API minuciosamente.
  2. Para los propósitos de estas condiciones, "API" se refiere a las APIs de Google, otros servicios para desarrolladores y el software asociado, inclusive cualquier Código Redistribuible.
  3. Se llama "Código Redistribuible" a lo que provee Google como código de objeto o los archivos de encabezado que llaman a las APIs.
  4. Sujeto a estas condiciones y las de las Condiciones del Servicio de la API, puedes copiar y distribuir únicamente el Código Redistribuible a modo de inclusión como parte del Cliente de API. Google y sus proveedores de licencias son propietarios de todos los derechos, intereses y títulos; asimismo, de toda propiedad intelectual, otros derechos de propiedad y el Código Redistribuible. No modificarás, trasladarás ni crearás obras derivadas del Código Redistribuible.
  5. Google puede publicar un aviso sobre cambios en las condiciones en cualquier momento y brindará la opción de rechazar el uso del kit de desarrollo de software de Play Core. Google avisará sobre las modificaciones a las condiciones en https://developer.android.com/guide/playcore/license. Los cambios no se aplicarán de forma retroactiva.
Descargar Play Core Native SDK

play-core-native-sdk-1.12.1.zip

  1. Elige una de las siguientes opciones:

  2. Prepara Android Studio para el desarrollo nativo con SDK Manager para instalar la versión más reciente del kit de desarrollo nativo (NDK) de CMake y Android. Obtén más información para crear o importar proyectos nativos en la sección Cómo comenzar a usar el NDK.

  3. Descarga el archivo ZIP y extráelo junto con tu proyecto.

    Vínculo de descarga Tamaño Suma de comprobación SHA-256
    70.9 MiB 84c9e9579f05d6e29bbbd9c9cde2fde8210947f2007866b0045f4c40fabb7368
  4. Actualiza el archivo build.gradle de tu app como se muestra a continuación:

    Groovy

        // App build.gradle
    
        plugins {
          id 'com.android.application'
        }
    
        // Define a path to the extracted Play Core SDK files.
        // If using a relative path, wrap it with file() since CMake requires absolute paths.
        def playcoreDir = file('../path/to/playcore-native-sdk')
    
        android {
            defaultConfig {
                ...
                externalNativeBuild {
                    cmake {
                        // Define the PLAYCORE_LOCATION directive.
                        arguments "-DANDROID_STL=c++_static",
                                  "-DPLAYCORE_LOCATION=$playcoreDir"
                    }
                }
                ndk {
                    // Skip deprecated ABIs. Only required when using NDK 16 or earlier.
                    abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64'
                }
            }
            buildTypes {
                release {
                    // Include Play Core Library proguard config files to strip unused code while retaining the Java symbols needed for JNI.
                    proguardFile '$playcoreDir/proguard/common.pgcfg'
                    proguardFile '$playcoreDir/proguard/gms_task.pgcfg'
                    proguardFile '$playcoreDir/proguard/per-feature-proguard-files'
                    ...
                }
                debug {
                    ...
                }
            }
            externalNativeBuild {
                cmake {
                    path 'src/main/CMakeLists.txt'
                }
            }
        }
    
        dependencies {
            // Import these feature-specific AARs for each Google Play Core library.
            implementation 'com.google.android.play:app-update:2.0.0'
            implementation 'com.google.android.play:asset-delivery:2.0.0'
            implementation 'com.google.android.play:integrity:1.0.1'
            implementation 'com.google.android.play:review:2.0.0'
    
            // Import these common dependencies.
            implementation 'com.google.android.gms:play-services-tasks:18.0.2'
            implementation files("$playcoreDir/playcore-native-metadata.jar")
            ...
        }
        

    Kotlin

    // App build.gradle
    
    plugins {
        id("com.android.application")
    }
    
    // Define a path to the extracted Play Core SDK files.
    // If using a relative path, wrap it with file() since CMake requires absolute paths.
    val playcoreDir = file("../path/to/playcore-native-sdk")
    
    android {
        defaultConfig {
            ...
            externalNativeBuild {
                cmake {
                    // Define the PLAYCORE_LOCATION directive.
                    arguments += listOf("-DANDROID_STL=c++_static", "-DPLAYCORE_LOCATION=$playcoreDir")
                }
            }
            ndk {
                // Skip deprecated ABIs. Only required when using NDK 16 or earlier.
                abiFilters.clear()
                abiFilters += listOf("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
            }
        }
        buildTypes {
            release {
                // Include Play Core Library proguard config files to strip unused code while retaining the Java symbols needed for JNI.
                proguardFile("$playcoreDir/proguard/common.pgcfg")
                proguardFile("$playcoreDir/proguard/gms_task.pgcfg")
                proguardFile("$playcoreDir/proguard/per-feature-proguard-files")
                ...
            }
            debug {
                ...
            }
        }
        externalNativeBuild {
            cmake {
                path = "src/main/CMakeLists.txt"
            }
        }
    }
    
    dependencies {
        // Import these feature-specific AARs for each Google Play Core library.
        implementation("com.google.android.play:app-update:2.0.0")
        implementation("com.google.android.play:asset-delivery:2.0.0")
        implementation("com.google.android.play:integrity:1.0.1")
        implementation("com.google.android.play:review:2.0.0")
    
        // Import these common dependencies.
        implementation("com.google.android.gms:play-services-tasks:18.0.2")
        implementation(files("$playcoreDir/playcore-native-metadata.jar"))
        ...
    }
    
  5. Actualiza los archivos CMakeLists.txt de tu app como se muestra a continuación:

    cmake_minimum_required(VERSION 3.6)
    
    ...
    
    # Add a static library called “playcore” built with the c++_static STL.
    include(${PLAYCORE_LOCATION}/playcore.cmake)
    add_playcore_static_library()
    
    // In this example “main” is your native code library, i.e. libmain.so.
    add_library(main SHARED
            ...)
    
    target_include_directories(main PRIVATE
            ${PLAYCORE_LOCATION}/include
            ...)
    
    target_link_libraries(main
            android
            playcore
            ...)
    

Recopilación de datos

El SDK nativo de Play Core puede recopilar datos relacionados con la versión para permitir que Google mejore el producto, por ejemplo:

  • Nombre del paquete de la app
  • Versión del paquete de la app
  • Versión del SDK nativo de Play Core

Estos datos se recopilarán cuando subas el paquete de tu app a Play Console. Para inhabilitar este proceso de recopilación de datos, quita la importación de $playcoreDir/playcore-native-metadata.jar en el archivo build.gradle.

Ten en cuenta que la recopilación de datos relacionada con tu uso del SDK nativo de Play Core y el uso que Google hace de los datos recopilados es independiente de la colección de dependencias de bibliotecas declarada por Google en Gradle cuando subes tu paquete de app a Play Console.

Entrega durante la instalación

Los paquetes de elementos configurados como install-time están disponibles apenas se inicia la app. Usa la API de NDK de AAssetManager para acceder a los elementos que se entregan en este modo:

#include <android/asset_manager.h>
#include <android_native_app_glue.h>
...
AAssetManager* assetManager = app->activity->assetManager;
AAsset* asset = AAssetManager_open(assetManager, "asset-name", AASSET_MODE_BUFFER);
size_t assetLength = AAsset_getLength(asset);
char* buffer = (char*) malloc(assetLength + 1);
AAsset_read(asset, buffer, assetLength);

Entrega rápida y a pedido

En las siguientes secciones, se muestra cómo inicializar la API, obtener información sobre los paquetes de elementos antes de descargarlos, llamar a la API para iniciar la descarga y acceder a los paquetes descargados. Estas secciones se aplican a los paquetes de elementos fast-follow y on-demand.

Inicio de la app

Siempre llama a AssetPackManager_init() para inicializar la API del paquete de elementos antes de llamar a cualquier otra función. Comprueba si hay códigos de error del paquete de elementos.

#include "play/asset_pack.h"
...
AssetPackErrorCode AssetPackManager_init(JavaVM* jvm, jobject android_context);

Además, asegúrate de llamar a las siguientes funciones en onPause() y onResume() de ANativeActivityCallbacks:

Obtén información de descarga sobre paquetes de elementos

Las apps deben divulgar el tamaño de la descarga antes de recuperar el paquete de elementos. Usa la función AssetPackManager_requestInfo() para iniciar una solicitud asíncrona para el tamaño de la descarga y aunque el paquete ya se esté descargando. Luego, usa AssetPackManager_getDownloadState() para sondear el estado de descarga (por ejemplo, llama a esta función una vez por fotograma en el bucle de juego). Si falla una solicitud, consulta los códigos de error del paquete de recursos.

AssetPackErrorCode AssetPackManager_requestInfo();      // Call once
AssetPackErrorCode AssetPackManager_getDownloadState(); // Call once per frame in your game loop

La función AssetPackManager_getDownloadState() muestra el tipo opaco AssetPackDownloadState como un puntero de salida. Usa ese puntero para llamar a las siguientes funciones:

AssetPackDownloadState* state;
AssetPackErrorCode error_code = AssetPackManager_getDownloadState(asset-pack-name, &state);
AssetPackDownloadStatus status = AssetPackDownloadState_getStatus(state);
uint64_t downloadedBytes = AssetPackDownloadState_getBytesDownloaded(state);
uint64_t totalBytes = AssetPackDownloadState_getTotalBytesToDownload(state));
AssetPackDownloadState_destroy(state);

Instalar

Usa AssetPackManager_requestDownload() para comenzar a descargar un paquete de elementos por primera vez o solicitar que se complete la actualización de un paquete:

AssetPackErrorCode AssetPackManager_requestDownload();  // Call once
AssetPackErrorCode AssetPackManager_getDownloadState(); // Call once per frame in your game loop

La función AssetPackManager_getDownloadState() muestra el tipo opaco AssetPackDownloadState. Para obtener información sobre cómo usar este tipo, consulta Obtén información de descarga.

Descargas grandes

Si la descarga supera los 150 MB y el usuario no está conectado a una red Wi-Fi, no se iniciará la descarga hasta que el usuario otorgue explícitamente su consentimiento para proceder con la descarga mediante una conexión de datos móviles. Del mismo modo, si la descarga es grande y el usuario pierde la conexión Wi-Fi, se detendrá el proceso y se necesitará el consentimiento explícito para continuar usando una conexión de datos móviles. Un paquete detenido tiene el estado WAITING_FOR_WIFI. Para activar el flujo de la IU y solicitar el consentimiento del usuario, usa lo siguiente:

Accede a los paquetes de elementos

Puedes acceder a un paquete de elementos mediante llamadas al sistema de archivos después de que la solicitud de descarga alcance el estado COMPLETED. Cada paquete de elementos se almacena en un directorio independiente, en el almacenamiento interno de la app. Usa AssetPackManager_getAssetPackLocation() a los efectos de obtener un AssetPackLocation para el paquete de elementos especificado. Usa AssetPackLocation_getStorageMethod() en esa ubicación para determinar el método de almacenamiento:

  • ASSET_PACK_STORAGE_APK: el paquete de elementos se instala como un APK. Consulta Entrega durante la instalación para acceder a estos elementos.
  • ASSET_PACK_STORAGE_FILES: usa AssetPackLocation_getAssetsPath() para obtener una ruta de acceso del archivo al directorio que contiene los elementos, o valores nulos si estos no se descargaron. No modifiques los archivos descargados en esta ruta de acceso del archivo.
AssetPackLocation* location;

AssetPackErrorCode error_code = AssetPackManager_getAssetPackLocation(asset-pack-name, &location);

if (error_code == ASSET_PACK_NO_ERROR) {
    AssetPackStorageMethod storage_method = AssetPackLocation_getStorageMethod(location);
    const char* assets_path = AssetPackLocation_getAssetsPath(location);
    AssetPackLocation_destroy(location);
}

Una vez que encuentres los elementos, usa funciones como fopen o ifstream para acceder a los archivos.

Otros métodos de la API de Play Core

Estos son algunos métodos de API adicionales que recomendamos que uses en tu app.

Cancelar solicitud

Usa AssetPackManager_cancelDownload() para cancelar una solicitud activa de paquete de elementos. Ten en cuenta que esta solicitud es una operación de mejor esfuerzo.

Solicitar eliminación

Usa AssetPackManager_requestRemoval() para programar la eliminación de un paquete de elementos.

Siguiente paso

Prueba Play Asset Delivery de forma local y desde Google Play.