Sigue los pasos que se indican en esta guía para acceder a los paquetes de recursos de tu app desde el código de Java.
Cómo compilar para Kotlin y Java
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.
Actualiza la versión del complemento de Android para Gradle en el archivo
build.gradle
de tu proyecto a4.0.0
o a una versión posterior.En el directorio de nivel superior de tu proyecto, crea un directorio para el paquete de recursos. Se usa el nombre de ese directorio como el nombre del paquete de recursos. Los nombres de los paquetes de recursos deben comenzar con una letra y solo pueden contener letras, números y guiones bajos.
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 recursos y solo un tipo de entrega:Groovy
// 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 ]" } }
Kotlin
// In the asset pack's build.gradle.kts file: plugins { id("com.android.asset-pack") } assetPack { packName.set("asset-pack-name") // Directory name for the asset pack dynamicDelivery { deliveryType.set("[ install-time | fast-follow | on-demand ]") } }
En el archivo
build.gradle
de la app del proyecto, agrega el nombre de cada paquete de recursos de tu proyecto, como se muestra a continuación:Groovy
// In the app build.gradle file: android { ... assetPacks = [":asset-pack-name", ":asset-pack2-name"] }
Kotlin
// In the app build.gradle.kts file: android { ... assetPacks += listOf(":asset-pack-name", ":asset-pack2-name") }
En el archivo
settings.gradle
del proyecto, incluye todos los paquetes de recursos de tu proyecto, como se muestra a continuación:Groovy
// In the settings.gradle file: include ':app' include ':asset-pack-name' include ':asset-pack2-name'
Kotlin
// In the settings.gradle.kts file: include(":app") include(":asset-pack-name") include(":asset-pack2-name")
En el directorio del paquete de recursos, crea el siguiente subdirectorio:
src/main/assets
.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
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 recursos.asset-pack-name/assets/your-asset-directories
: Es el directorio que contiene todos los recursos entregados como parte del paquete de recursos.
Gradle genera el manifiesto para cada paquete de recursos y genera el directorio
assets/
por ti.Opcional: Incluye la biblioteca de Play Asset Delivery si planeas usar la entrega de seguimiento rápido y a pedido.
Groovy
implementation "com.google.android.play:asset-delivery:2.2.2" // For Kotlin use asset-delivery-ktx implementation "com.google.android.play:asset-delivery-ktx:2.2.2"
Kotlin
implementation("com.google.android.play:asset-delivery:2.2.2") // For Kotlin use core-ktx implementation("com.google.android.play:asset-delivery-ktx:2.2.2")
Opcional: Configura el paquete de aplicación para que sea compatible con diferentes formatos de compresión de texturas.
Integra la API de Play Asset Delivery
La API de Java de Play Asset Delivery proporciona la clase AssetPackManager
para solicitar paquetes de recursos, administrar descargas y acceder a los recursos. Primero, asegúrate de agregar la biblioteca de Play Asset Delivery a tu proyecto.
Esta API se implementa de acuerdo con el tipo de entrega del paquete de recursos al que deseas acceder. Estos pasos se muestran en el siguiente diagrama de flujo.
Entrega durante la instalación
Los paquetes de recursos configurados como install-time
están disponibles apenas se inicia la app. Usa la API de AssetManager de Java para acceder a los recursos que se entregan en este modo:
Kotlin
import android.content.res.AssetManager ... val context: Context = createPackageContext("com.example.app", 0) val assetManager: AssetManager = context.assets val stream: InputStream = assetManager.open("asset-name")
Java
import android.content.res.AssetManager; ... Context context = createPackageContext("com.example.app", 0); AssetManager assetManager = context.getAssets(); InputStream is = assetManager.open("asset-name");
Cómo realizar entregas rápidas y a pedido
En las siguientes secciones, se muestra cómo obtener información sobre los paquetes de recursos antes de descargarlos, cómo llamar a la API para comenzar la descarga y cómo acceder a los paquetes descargados. Estas secciones se aplican a los paquetes de recursos fast-follow
y on-demand
.
Comprueba el estado
Cada paquete de recursos se almacena en una carpeta independiente del almacenamiento interno de la app.
Usa el método getPackLocation()
para determinar la carpeta raíz de un paquete de recursos. Este método devuelve los siguientes valores:
Valor que se devuelve | Estado |
---|---|
Un objeto AssetPackLocation válido |
La carpeta raíz del paquete de recursos está lista para acceder de inmediato a assetsPath() |
null |
Los paquetes de recursos o los recursos desconocidos no están disponibles |
Obtén información de descarga sobre paquetes de recursos
Las apps deben divulgar el tamaño de la descarga antes de recuperar el paquete de recursos. Usa el método requestPackStates()
o getPackStates()
para determinar el tamaño de la descarga y si ya se está descargando el paquete.
Kotlin
suspend fun requestPackStates(packNames: List<String>): AssetPackStates
Java
Task<AssetPackStates> getPackStates(List<String> packNames)
requestPackStates()
es una función de suspensión que devuelve un objeto AssetPackStates
, mientras que getPackStates()
es un método asíncrono que devuelve un elemento Task<AssetPackStates>
. El método packStates()
de un objeto AssetPackStates
devuelve un elemento Map<String,
AssetPackState>
. Este mapa contiene el estado de cada paquete de recursos solicitado, codificado por su nombre:
Kotlin
AssetPackStates#packStates(): Map<String, AssetPackState>
Java
Map<String, AssetPackState> AssetPackStates#packStates()
La solicitud final se muestra mediante lo siguiente:
Kotlin
const val assetPackName = "assetPackName" coroutineScope.launch { try { val assetPackStates: AssetPackStates = manager.requestPackStates(listOf(assetPackName)) val assetPackState: AssetPackState = assetPackStates.packStates()[assetPackName] } catch (e: RuntimeExecutionException) { Log.d("MainActivity", e.message) } }
Java
final String assetPackName = "myasset"; assetPackManager .getPackStates(Collections.singletonList(assetPackName)) .addOnCompleteListener(new OnCompleteListener<AssetPackStates>() { @Override public void onComplete(Task<AssetPackStates> task) { AssetPackStates assetPackStates; try { assetPackStates = task.getResult(); AssetPackState assetPackState = assetPackStates.packStates().get(assetPackName); } catch (RuntimeExecutionException e) { Log.d("MainActivity", e.getMessage()); return; })
Los siguientes métodos AssetPackState
proporcionan el tamaño del paquete de recursos, la cantidad descargada hasta el momento (si se solicita) y la cantidad que ya se transfirió a la app:
Para obtener el estado de un paquete de recursos, usa el método status()
que devuelve el estado como un número entero que corresponde a un campo constante en la clase AssetPackStatus
. Un paquete de recursos que aún no está instalado tiene el estado AssetPackStatus.NOT_INSTALLED
.
Si falla una solicitud, usa el método errorCode()
, cuyo valor que se devuelve corresponde a un campo constante en la clase AssetPackErrorCode
.
Instalación
Usa el método requestFetch()
o fetch()
para descargar un paquete de recursos por primera vez o realiza la llamada para que se complete la actualización de un paquete:
Kotlin
suspend fun AssetPackManager.requestFetch(packs: List<String>): AssetPackStates
Java
Task<AssetPackStates> fetch(List<String> packNames)
Este método devuelve un objeto AssetPackStates
que contiene una lista de paquetes y sus estados y tamaños de descarga iniciales.
Si ya se está descargando un paquete de recursos solicitado a través de requestFetch()
o fetch()
, se devolverá el estado de descarga y no se iniciará ninguna descarga adicional.
Supervisa los estados de descarga
Debes implementar un objeto AssetPackStateUpdatedListener
para realizar un seguimiento del progreso de la instalación de paquetes de recursos. Las actualizaciones de estado se desglosan por paquete para admitir el seguimiento del estado de paquetes de recursos individuales. Puedes comenzar a usar los paquetes de recursos disponibles antes de que se completen todas las demás descargas de la solicitud.
Kotlin
fun registerListener(listener: AssetPackStateUpdatedListener) fun unregisterListener(listener: AssetPackStateUpdatedListener)
Java
void registerListener(AssetPackStateUpdatedListener listener) void unregisterListener(AssetPackStateUpdatedListener listener)
Descargas grandes
Si la descarga supera los 200 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 continuar 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, esta se detiene y se necesita 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 el método showConfirmationDialog()
.
Ten en cuenta que si la app no llama a este método, la descarga se detiene y se reanudará automáticamente cuando el usuario vuelva a una conexión Wi-Fi.
Confirmación del usuario obligatoria
Si un paquete tiene el estado REQUIRES_USER_CONFIRMATION
, la descarga no continuará hasta que el usuario acepte el diálogo que se muestra con showConfirmationDialog()
.
Este estado puede ocurrir cuando Play no reconoce la app, por ejemplo, si se transfirió.
Ten en cuenta que llamar a showConfirmationDialog()
en este caso hará que se actualice la app. Después de la actualización, deberás volver a solicitar los recursos.
A continuación, se muestra un ejemplo de implementación de un objeto de escucha:
Kotlin
private val activityResultLauncher = registerForActivityResult( ActivityResultContracts.StartIntentSenderForResult() ) { result -> if (result.resultCode == RESULT_OK) { Log.d(TAG, "Confirmation dialog has been accepted.") } else if (result.resultCode == RESULT_CANCELED) { Log.d(TAG, "Confirmation dialog has been denied by the user.") } } assetPackManager.registerListener { assetPackState -> when(assetPackState.status()) { AssetPackStatus.PENDING -> { Log.i(TAG, "Pending") } AssetPackStatus.DOWNLOADING -> { val downloaded = assetPackState.bytesDownloaded() val totalSize = assetPackState.totalBytesToDownload() val percent = 100.0 * downloaded / totalSize Log.i(TAG, "PercentDone=" + String.format("%.2f", percent)) } AssetPackStatus.TRANSFERRING -> { // 100% downloaded and assets are being transferred. // Notify user to wait until transfer is complete. } AssetPackStatus.COMPLETED -> { // Asset pack is ready to use. Start the game. } AssetPackStatus.FAILED -> { // Request failed. Notify user. Log.e(TAG, assetPackState.errorCode()) } AssetPackStatus.CANCELED -> { // Request canceled. Notify user. } AssetPackStatus.WAITING_FOR_WIFI, AssetPackStatus.REQUIRES_USER_CONFIRMATION -> { if (!confirmationDialogShown) { assetPackManager.showConfirmationDialog(activityResultLauncher); confirmationDialogShown = true } } AssetPackStatus.NOT_INSTALLED -> { // Asset pack is not downloaded yet. } AssetPackStatus.UNKNOWN -> { Log.wtf(TAG, "Asset pack status unknown") } } }
Java
assetPackStateUpdateListener = new AssetPackStateUpdateListener() { private final ActivityResultLauncher<IntentSenderRequest> activityResultLauncher = registerForActivityResult( new ActivityResultContracts.StartIntentSenderForResult(), new ActivityResultCallback<ActivityResult>() { @Override public void onActivityResult(ActivityResult result) { if (result.getResultCode() == RESULT_OK) { Log.d(TAG, "Confirmation dialog has been accepted."); } else if (result.getResultCode() == RESULT_CANCELED) { Log.d(TAG, "Confirmation dialog has been denied by the user."); } } }); @Override public void onStateUpdate(AssetPackState assetPackState) { switch (assetPackState.status()) { case AssetPackStatus.PENDING: Log.i(TAG, "Pending"); break; case AssetPackStatus.DOWNLOADING: long downloaded = assetPackState.bytesDownloaded(); long totalSize = assetPackState.totalBytesToDownload(); double percent = 100.0 * downloaded / totalSize; Log.i(TAG, "PercentDone=" + String.format("%.2f", percent)); break; case AssetPackStatus.TRANSFERRING: // 100% downloaded and assets are being transferred. // Notify user to wait until transfer is complete. break; case AssetPackStatus.COMPLETED: // Asset pack is ready to use. Start the game. break; case AssetPackStatus.FAILED: // Request failed. Notify user. Log.e(TAG, assetPackState.errorCode()); break; case AssetPackStatus.CANCELED: // Request canceled. Notify user. break; case AssetPackStatus.WAITING_FOR_WIFI: case AssetPackStatus.REQUIRES_USER_CONFIRMATION: if (!confirmationDialogShown) { assetPackManager.showConfirmationDialog(activityResultLauncher); confirmationDialogShown = true; } break; case AssetPackStatus.NOT_INSTALLED: // Asset pack is not downloaded yet. break; case AssetPackStatus.UNKNOWN: Log.wtf(TAG, "Asset pack status unknown") break; } } }
También puedes usar el método getPackStates()
para obtener el estado de las descargas actuales.
AssetPackStates
contiene el progreso de descarga, el estado de descarga y los códigos de error con fallas.
Accede a los paquetes de recursos
Puedes acceder a un paquete de recursos mediante llamadas al sistema de archivos después de que la solicitud de descarga alcanza el estado COMPLETED
. Usa el método getPackLocation()
para obtener la carpeta raíz del paquete de recursos.
Los recursos se almacenan en el directorio assets
dentro del directorio raíz del paquete de recursos. Puedes obtener la ruta al directorio assets
con el método útil assetsPath()
.
Usa el siguiente método para obtener la ruta a un recurso específico:
Kotlin
private fun getAbsoluteAssetPath(assetPack: String, relativeAssetPath: String): String? { val assetPackPath: AssetPackLocation = assetPackManager.getPackLocation(assetPack) // asset pack is not ready ?: return null val assetsFolderPath = assetPackPath.assetsPath() // equivalent to: FilenameUtils.concat(assetPackPath.path(), "assets") return FilenameUtils.concat(assetsFolderPath, relativeAssetPath) }
Java
private String getAbsoluteAssetPath(String assetPack, String relativeAssetPath) { AssetPackLocation assetPackPath = assetPackManager.getPackLocation(assetPack); if (assetPackPath == null) { // asset pack is not ready return null; } String assetsFolderPath = assetPackPath.assetsPath(); // equivalent to: FilenameUtils.concat(assetPackPath.path(), "assets"); String assetPath = FilenameUtils.concat(assetsFolderPath, relativeAssetPath); return assetPath; }
Otros métodos de la API de Play Asset Delivery
Estos son algunos métodos de API adicionales que te recomendamos que uses en tu app.
Cancela una solicitud
Usa cancel()
para cancelar una solicitud activa de paquete de recursos. Ten en cuenta que esta solicitud es una operación de mejor esfuerzo.
Quita un paquete de recursos
Usa el método requestRemovePack()
o removePack()
para programar la eliminación de un paquete de recursos.
Obtén las ubicaciones de varios paquetes de recursos
Usa getPackLocations()
para consultar el estado de varios paquetes de recursos de forma masiva, lo que devuelve un mapa de los paquetes de recursos y sus ubicaciones. El mapa que devuelve getPackLocations()
contiene una entrada para cada paquete que se descarga y está actualizado.
Siguiente paso
Prueba Play Asset Delivery de forma local y desde Google Play.