请按照本指南中的步骤,通过 C 和 C++ 代码访问您应用的素材资源包。
示例集成代码可在 GitHub 上获取。
为原生构建
请按照以下步骤将 Play Asset Delivery 构建到您的项目的 Android App Bundle 中。您无需使用 Android Studio 来执行这些步骤。
将您项目
build.gradle
文件中的 Android Gradle 插件版本更新到4.0.0
或更高版本。在项目顶层目录中,为素材资源包创建一个目录。此目录名称将用作素材资源包名称。素材资源包名称必须以字母开头,且只能包含字母、数字和下划线。
在素材资源包目录中,创建一个
build.gradle
文件并添加以下代码。请务必指定素材资源包的名称和一种交付类型。// 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 ]" } }
在项目的应用
build.gradle
文件中,添加项目中每个素材资源包的名称,如下所示:// In the app build.gradle file: android { ... assetPacks = [":asset-pack-name", ":asset-pack2-name"] }
在项目的
settings.gradle
文件中,包含项目中所有的素材资源包,如下所示:// In the settings.gradle file: include ':app' include ':asset-pack-name' include ':asset-pack2-name'
在素材资源包目录中,创建以下子目录:
src/main/assets
。将素材资源放置在
src/main/assets
目录中。您也可以在此处创建子目录。您的应用目录结构现在应如下所示:build.gradle
settings.gradle
app/
asset-pack-name/build.gradle
asset-pack-name/src/main/assets/your-asset-directories
使用 Gradle 构建 Android App Bundle。在生成的应用 bundle 中,根级目录现在包含以下内容:
asset-pack-name/manifest/AndroidManifest.xml
:配置素材资源包的标识符和交付模式asset-pack-name/assets/your-asset-directories
:包含作为素材资源包一部分交付的所有素材资源的目录
Gradle 会为每个素材资源包生成清单,并为您输出
assets/
目录。(可选)配置您的应用 bundle 以支持不同的纹理压缩格式。
与 Play Asset Delivery 库集成
您需要根据要访问的素材资源包的交付类型来实现此 API。以下流程图显示了这些步骤。
图 1. 访问素材资源包的流程图
Play Core Native SDK 提供了 C 头文件 play/asset_pack.h
,用于请求素材资源包、管理下载以及访问素材资源。
为 Play Core Native SDK 设置开发环境
下载 Play Core Native SDK
下载前,您必须同意以下条款和条件。
条款和条件
最后修改日期:2020 年 9 月 24 日- 使用 Play Core 软件开发工具包,即表示您同意这些条款以及 Google API 服务条款(“API 服务条款”)。如果这些条款之间发生冲突,则以这些条款为准。请仔细阅读这些条款和 API 服务条款。
- 就这些条款而言,“API”指 Google 的 API、其他开发者服务以及相关软件,包括任何可再分发代码。
- “可再分发代码”指 Google 提供的调用 API 的目标代码或头文件。
- 根据这些条款和 API 服务条款的规定,您只能复制和分发可再分发代码,以作为您的 API 客户端的一部分。Google 及其许可方拥有可再分发代码中的所有权利、所有权和利益,包括任何及所有知识产权和其他所有权。您不得修改、翻译或创建可再分发代码的衍生作品。
- Google 可随时通知您并提供机会拒绝继续使用 Play Core 软件开发工具包,从而更改这些条款。Google 将在 https://developer.android.com/guide/playcore/license 发布条款修改通知。更改不具有追溯力。
执行以下任一操作:
- 安装 Android Studio 4.0 或更高版本。使用 SDK Manager 界面安装 Android SDK Platform 10.0(API 级别 29)。
- 安装 Android SDK 命令行工具,并使用
sdkmanager
安装 Android SDK Platform 10.0(API 级别 29)。
使用 SDK Manager 安装最新的 CMake 和 Android 原生开发套件 (NDK),为原生开发准备 Android Studio。如需详细了解如何创建或导入原生项目,请参阅NDK 入门。
下载 zip 文件并将其解压到项目旁边。
下载链接 大小 SHA-256 校验和 37.8 MiB 9db60185185342f28d2c278b60222333608c67bc022e458a25224eaea8c4c4b7 更新您的应用
build.gradle
文件,如下所示: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.1.0' implementation 'com.google.android.play:asset-delivery:2.3.0' implementation 'com.google.android.play:integrity:1.4.0' implementation 'com.google.android.play:review:2.0.2' // 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.1.0") implementation("com.google.android.play:asset-delivery:2.3.0") implementation("com.google.android.play:integrity:1.4.0") implementation("com.google.android.play:review:2.0.2") // Import these common dependencies. implementation("com.google.android.gms:play-services-tasks:18.0.2") implementation(files("$playcoreDir/playcore-native-metadata.jar")) ... }
更新您的应用
CMakeLists.txt
文件,如下所示: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 ...)
数据收集
Play Core Native SDK 可能会收集与版本相关的数据,以帮助 Google 改进产品,包括:
- 应用的软件包名称
- 应用的软件包版本
- Play Core Native SDK 的版本
当您将您的应用软件包上传到 Play 管理中心时,将收集此数据。要选择退出此数据收集过程,请移除 build.gradle 文件中 $playcoreDir/playcore-native-metadata.jar
的导入。
请注意,与您使用 Play Core Native SDK 和 Google 使用所收集数据相关的数据收集,独立于您将应用软件包上传到 Play 管理中心时 Google 收集 Gradle 中声明的库依赖项。
安装时交付
配置为 install-time
的素材资源包在应用启动时立即可用。使用 NDK AAssetManager API 来访问以此模式提供的素材资源。
#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);
快速跟进和按需交付
以下部分展示了如何初始化 API、如何在下载素材资源包之前获取有关它们的信息、如何调用 API 开始下载以及如何访问已下载的素材资源包。这些部分适用于 fast-follow
和 on-demand
素材资源包。
应用启动
在调用任何其他函数之前,始终调用 AssetPackManager_init()
来初始化素材资源包 API。检查是否存在任何素材资源包错误代码。
#include "play/asset_pack.h" ... AssetPackErrorCode AssetPackManager_init(JavaVM* jvm, jobject android_context);
另外,请务必在 ANativeActivityCallbacks
的 onPause()
和 onResume()
中调用以下函数:
获取素材资源包的下载信息
应用必须在获取素材资源包之前披露下载大小。使用 AssetPackManager_requestInfo()
函数启动一个异步请求,以获取下载大小以及素材资源包是否已在下载。然后使用 AssetPackManager_getDownloadState()
轮询下载状态(例如,在游戏循环中每帧调用此函数一次)。如果请求失败,请检查素材资源包错误代码。
AssetPackErrorCode AssetPackManager_requestInfo(); // Call once AssetPackErrorCode AssetPackManager_getDownloadState(); // Call once per frame in your game loop
AssetPackManager_getDownloadState()
函数将不透明类型 AssetPackDownloadState
作为输出指针返回。使用此指针调用以下函数:
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);
安装
使用 AssetPackManager_requestDownload()
首次开始下载素材资源包或请求完成素材资源包更新。
AssetPackErrorCode AssetPackManager_requestDownload(); // Call once AssetPackErrorCode AssetPackManager_getDownloadState(); // Call once per frame in your game loop
AssetPackManager_getDownloadState()
函数返回不透明类型 AssetPackDownloadState
。有关如何使用此类型的信息,请参阅获取下载信息。
大文件下载
如果下载文件大于 200MB 且用户未连接 Wi-Fi,则下载不会开始,除非用户明确同意使用移动数据连接继续下载。同样,如果下载文件很大且用户失去 Wi-Fi 连接,下载将暂停,并且需要明确同意才能使用移动数据连接继续。暂停的素材资源包状态为 WAITING_FOR_WIFI
。要触发 UI 流程以提示用户同意,请使用以下方法:
需要用户确认
如果素材资源包的状态为 REQUIRES_USER_CONFIRMATION
,则下载不会继续,直到用户接受通过 AssetPackManager_showConfirmationDialog()
显示的对话框。如果 Play 未识别该应用,可能会出现此状态。请注意,在这种情况下调用 AssetPackManager_showConfirmationDialog()
会导致应用更新。更新后,再次请求素材资源。
访问素材资源包
下载请求达到 COMPLETED
状态后,您可以使用文件系统调用来访问素材资源包。每个素材资源包都存储在应用内部存储中的一个单独目录中。使用 AssetPackManager_getAssetPackLocation()
获取指定素材资源包的 AssetPackLocation
。在该位置使用 AssetPackLocation_getStorageMethod()
确定存储方法:
ASSET_PACK_STORAGE_APK
:素材资源包作为 APK 安装。请参阅安装时交付以访问这些素材资源。ASSET_PACK_STORAGE_FILES
:使用AssetPackLocation_getAssetsPath()
获取包含素材资源的目录的文件路径;如果素材资源尚未下载,则为 null。请勿修改此文件路径中的已下载文件。
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); }
找到素材资源后,使用 fopen
或 ifstream
等函数访问文件。
其他 Play Core API 方法
以下是一些您可能希望在应用中使用的其他 API 方法。
取消请求
使用 AssetPackManager_cancelDownload()
取消活跃的素材资源包请求。请注意,此请求是尽力而为的操作。
请求移除
使用 AssetPackManager_requestRemoval()
安排移除素材资源包。
后续步骤
测试 Play Asset Delivery(本地和 Google Play)。