Play Core API 集成
请务必先将 Play Core 库添加到你的项目中。
Play Core Java API 提供了用于请求资源包、管理下载内容和获取资源的 AssetPackManager 类。请务必先将 Play Core 库添加到你的项目中。 你可以根据希望获取的资源包的分发类型来实现此 API。这些步骤如以下流程图所示。
注意: 用于获取 install-time Asset Pack 的 API 与用于获取 fast-follow 和 on-demand Asset Pack 的 API 不同。
安装时分发
配置为 install-time 的资源包可以在应用启动后立即使用。使用 Java AssetManager API 获取在此模式下提供的资产:
import android.content.res.AssetManager; ... Context context = createPackageContext("com.example.app", 0); AssetManager assetManager = context.getAssets(); InputStream is = assetManager.open("asset-name");
快速跟进式分发和按需分发
以下几部分介绍了如何在下载 Asset Pack 前获取其相关信息、如何调用 API 以开始下载,以及之后如何获取已下载的 Asset Pack。这几部分适用于 fast-follow 和 on-demand Asset Pack。
查看状态
每个资源包都存储于应用的内部存储空间内单独的文件夹中。使用 getPackLocation() 方法确定 Asset Pack 的根文件夹。此方法会返回以下值:
- 有效的AssetPackLocation对象:资源包根文件夹位于 assetsPath(),现已可立即获取
- null:未知 Asset Pack 或资产无法使用
注意:请勿依赖在两次应用启动之间的间隔时间内缓存的 Asset Pack 位置。应用应在每次启动时始终检查是否存在 Asset Pack。Asset Pack 可能会因应用更新或用户清除应用数据而变为无效。
获取有关资源包的下载信息
在提取资源包之前,应用必须披露下载内容的大小。使用getPackStates() 方法确定下载内容的大小,以及资源包是否已在下载。
Task<AssetPackStates> getPackStates(List<String> packNames)
getPackStates() 是用于返回任务的异步方法。该任务的结果包含一个 AssetPackStates 对象。AssetPackStates 对象的 packStates() 方法会返回一个 Map<String, AssetPackState>。此映射包含所请求的每个 Asset Pack 的状态,按其名称进行键控:
Map<String, AssetPackState> AssetPackStates#packStates()
最终请求如下所示:
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; })
以下 AssetPackState 方法提供了资源包的大小、截至目前已下载的数据量(如已请求),以及已传输到应用的数据量:
- totalBytesToDownload()
- bytesDownloaded()
- transferProgressPercentage()
如需获取资源包的状态,请使用 status() 方法,该方法以整数形式返回与 AssetPackStatus 类中某个常量字段相对应的状态。尚未安装的资源包状态为 AssetPackStatus.NOT_INSTALLED。
如果请求失败,请使用 errorCode() 方法,该方法的返回值与 AssetPackErrorCode 类中的某个常量字段相对应。
安装
使用 fetch() 方法首次下载资源包,或要求进行资源包更新以完成操作:
Task<AssetPackStates> fetch(List<String> packNames)
此方法会返回一个 AssetPackStates 对象,其中包含资源包列表及其初始下载状态和大小。如果通过 fetch() 请求的 Asset Pack 已经在下载,就会返回下载状态,并且不会启动其他下载。
注意:在大多数情况下,你需要实现 listener 以跟踪下载和安装过程,如下一部分所述。
监控下载状态
你应实现 listener 以跟踪 Asset Pack 的安装进度。状态更新按 Asset Pack 细分,以支持跟踪各 Asset Pack 的状态。在请求的所有其他下载完成之前,你就可以开始使用已可供使用的资源包。
- void registerListener(AssetPackStateUpdatedListener listener)
- void unregisterListener(AssetPackStateUpdatedListener listener)
注意: 在用户安装或更新应用后,Play 商店会自动触发下载任何 fast-follow 资源包。不过,这些资源包可能无法立即供用户使用。你必须在每次应用启动时检查 fast-follow Asset Pack 的状态。如果下载正在进行,请使用监听器对其进行监控。如果下载已取消或暂停,你可以使用 fetch() 方法恢复下载,如安装部分所述。
下载内容较大
如果下载内。超过150MB并且用户未连接到 WLAN,那么在用户明确同意使用移动网络连接继续下载前,下载不会开始。同样,如果下载内容较大并且用户与 WLAN 的连接断开,下载会暂停,需要用户明确同意才能使用移动网络连接继续下载。已暂停的 Asset Pack 状态为 WAITING_FOR_WIFI。如需触发界面流程以提示用户同意,请使用 showCellularDataConfirmation() 方法。
请注意,如果应用不调用此方法,下载会暂停,并且只有当用户重新连接到 WLAN 时才会自动恢复下载。
以下是监听器的一个实现示例:
assetPackStateUpdateListener = new AssetPackStateUpdateListener() { @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: if (!waitForWifiConfirmationShown) { assetPackManager.showCellularDataConfirmation(MainActivity.this) .addOnSuccessListener(new OnSuccessListener<Integer> () { @Override public void onSuccess(Integer resultCode) { if (resultCode == RESULT_OK) { Log.d(TAG, "Confirmation dialog has been accepted."); } else if (resultCode == RESULT_CANCELED) { Log.d(TAG, "Confirmation dialog has been denied by the user."); } } }); waitForWifiConfirmationShown = true; } break; case AssetPackStatus.NOT_INSTALLED: // Asset pack is not downloaded yet. break; } } }
或者,你也可以使用 getPackStates() 方法获取当前下载的状态。AssetPackStates 包含下载进度、下载状态和任何失败的错误代码。
获取资源包
在下载请求达到 COMPLETED 状态后,你可以使用文件系统调用获取资源包。使用 getPackLocation() 方法获取资源包的根文件夹。
资源存储于资源包根目录内的 assets 目录下。你可以使用便捷方法 assetsPath() 获取 assets 目录的路径。请使用以下方法获取特定资产的路径:
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; }
取消请求
使用 cancel() 取消有效的资源包请求。请注意,此请求是尽力而为的操作。
移除资源包
使用 removePack() 安排移除资源包。
获取多个资源包的位置
使用 getPackLocations() 批量查询多个资源包的状态,此方法将返回资源包与其位置的映射。getPackLocations() 返回的映射包含当前已下载且为最新状态的每个 Asset Pack 的条目。