chunk 2: remaining non-audio non-NewImport assets

This commit is contained in:
2026-04-06 11:25:19 +03:00
parent 0d11a097d8
commit ed675b9f4a
3742 changed files with 1640416 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: dec718d77264f47449b48b38a4b90eea
timeCreated: 1581039935
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 155f33a169c84b3aa017d89e311f5346
timeCreated: 1652822769

View File

@@ -0,0 +1,6 @@
<dependencies>
<androidPackages>
<androidPackage spec="com.google.android.play:asset-delivery:2.2.1"/>
</androidPackages>
</dependencies>

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ccc5f5aabafe46e295073bf935d86741
timeCreated: 1652822770

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e60c7cccc4b054a659b554292a331d09
timeCreated: 1583983813
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: fa573c0a20edd43e78490ce1fadba009
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,118 @@
# Copyright 2019 Google LLC
#
# The Google Play Core Library is licensed to you under the Play Core Software
# Development Kit Terms of Service
# (https://developer.android.com/guide/playcore/license.html).
# By using the Google Play Core Library, you agree to the Play Core Software
# Development Kit Terms of Service.
# Play Core Proguard Rules: Play Asset Delivery for asset packs
-keep class com.google.android.play.core.assetpacks.AssetLocation {
public long offset();
public java.lang.String path();
public long size();
public java.lang.String toString();
}
-keep class com.google.android.play.core.assetpacks.AssetPackState {
public long bytesDownloaded();
public int transferProgressPercentage();
public int errorCode();
public java.lang.String name();
public int status();
public java.lang.String toString();
public long totalBytesToDownload();
public int updateAvailability();
public java.lang.String availableVersionTag();
public java.lang.String installedVersionTag();
}
-keep class com.google.android.play.core.assetpacks.AssetPackStates {
public java.util.Map packStates();
public java.lang.String toString();
public long totalBytes();
}
-keep class com.google.android.play.core.assetpacks.model.AssetPackErrorCode {
public static int ACCESS_DENIED;
public static int API_NOT_AVAILABLE;
public static int APP_NOT_OWNED;
public static int APP_UNAVAILABLE;
public static int CONFIRMATION_NOT_REQUIRED;
public static int DOWNLOAD_NOT_FOUND;
public static int INSUFFICIENT_STORAGE;
public static int INTERNAL_ERROR;
public static int INVALID_REQUEST;
public static int NETWORK_ERROR;
public static int NO_ERROR;
public static int PACK_UNAVAILABLE;
public static int UNRECOGNIZED_INSTALLATION;
}
-keep class com.google.android.play.core.assetpacks.AssetPackException {
public int getErrorCode();
}
-keep class com.google.android.play.core.assetpacks.AssetPackLocation {
public java.lang.String assetsPath();
public int packStorageMethod();
public java.lang.String path();
public java.lang.String toString();
}
-keep class com.google.android.play.core.assetpacks.AssetPackManager {
public com.google.android.play.core.assetpacks.AssetPackStates cancel(java.util.List);
public void clearListeners();
public com.google.android.play.core.assetpacks.AssetLocation getAssetLocation(java.lang.String, java.lang.String);
public com.google.android.play.core.assetpacks.AssetPackLocation getPackLocation(java.lang.String);
public java.util.Map getPackLocations();
public com.google.android.gms.tasks.Task getPackStates(java.util.List);
public com.google.android.gms.tasks.Task fetch(java.util.List);
public void registerListener(com.google.android.play.core.assetpacks.AssetPackStateUpdateListener);
public com.google.android.gms.tasks.Task removePack(java.lang.String);
public com.google.android.gms.tasks.Task showCellularDataConfirmation(android.app.Activity);
public com.google.android.gms.tasks.Task showConfirmationDialog(android.app.Activity);
public void unregisterListener(com.google.android.play.core.assetpacks.AssetPackStateUpdateListener);
}
-keep class com.google.android.play.core.assetpacks.AssetPackManagerFactory {
<init>();
public static com.google.android.play.core.assetpacks.AssetPackManager getInstance(android.content.Context);
}
-keep class com.google.android.play.core.assetpacks.AssetPackStateUpdateListener {
public void onStateUpdate(com.google.android.play.core.assetpacks.AssetPackState);
}
-keep class com.google.android.play.core.assetpacks.model.AssetPackStatus {
public static int CANCELED;
public static int COMPLETED;
public static int DOWNLOADING;
public static int FAILED;
public static int NOT_INSTALLED;
public static int PENDING;
public static int REQUIRES_USER_CONFIRMATION;
public static int TRANSFERRING;
public static int UNKNOWN;
public static int WAITING_FOR_WIFI;
}
-keep class com.google.android.play.core.assetpacks.model.AssetPackStorageMethod {
public static int APK_ASSETS;
public static int STORAGE_FILES;
}
-keep class com.google.android.play.core.assetpacks.NativeAssetPackStateUpdateListener {
<init>();
public void onStateUpdate(com.google.android.play.core.assetpacks.AssetPackState);
}
-keep class com.google.android.play.core.assetpacks.model.AssetPackUpdateAvailability {
public static int UNKNOWN;
public static int UPDATE_NOT_AVAILABLE;
public static int UPDATE_AVAILABLE;
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: b951803efef6642c7963f25bd9f66ec3
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6148018545ee34a66859753b5e6054a5
timeCreated: 1581040462
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: ec7a05216aa234fdc9ee0b33642cbd52
folderAsset: yes
timeCreated: 1576618908
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,11 @@
{
"name": "Google.Play.AssetDelivery",
"references": [
"Google.Play.Common",
"Google.Play.Core"
],
"includePlatforms": [
"Android",
"Editor"
]
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 870f26a2ffa82429195df0861505c5d5
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0b57410961ed54c8180f902be5f3d5ec
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
fileFormatVersion: 2
guid: 911769b6af96845e4803f50a85d2092c
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
isPreloaded: 0
isOverridable: 0
platformData:
- first:
Android: Android
second:
enabled: 1
settings: {}
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 4dbd1619141054c07aefeb3ca862c976
folderAsset: yes
timeCreated: 1580749599
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,110 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace Google.Play.AssetDelivery
{
/// <summary>
/// Errors that can be encountered while interacting with asset packs.
/// </summary>
public enum AssetDeliveryErrorCode
{
/// <summary>
/// No error has occurred.
/// </summary>
NoError = 0,
/// <summary>
/// The requesting app is unavailable.
///
/// <para>This could be caused by multiple reasons:
///
/// <list type="bullet">
/// <item><description>
/// The app isn't published in the Play Store.
/// </description></item>
/// <item><description>
/// The app version code isn't published in the Play Store. Note: an older version may exist.
/// </description></item>
/// <item><description>
/// The app is only available on a testing track that the user doesn't have access to.
/// </description></item>
/// </list>
/// </para>
/// </summary>
AppUnavailable = 1,
/// <summary>
/// The requested asset pack is unavailable.
/// </summary>
BundleUnavailable = 2,
/// <summary>
/// Network error. Unable to obtain asset pack details.
/// </summary>
NetworkError = 3,
/// <summary>
/// Download not permitted under current device circumstances, for example the app is running in the background.
/// </summary>
AccessDenied = 4,
/// <summary>
/// Asset pack installation failed due to insufficient storage.
/// </summary>
InsufficientStorage = 7,
/// <summary>
/// AssetBundle failed to load.
/// </summary>
AssetBundleLoadingError = 8,
/// <summary>
/// The download was cancelled, likely by the user cancelling the download notification.
/// </summary>
Canceled = 9,
/// <summary>
/// Unknown error retrieving asset pack.
/// </summary>
InternalError = 10,
/// <summary>
/// The Play Store app is either not installed or not the official version.
/// </summary>
PlayStoreNotFound = 11,
/// <summary>
/// Returned if <see cref="PlayAssetDelivery.ShowCellularDataConfirmation"/> is called but
/// no asset packs are waiting for Wi-Fi.
/// </summary>
NetworkUnrestricted = 12,
/// <summary>
/// The app isn't owned by any user on this device. An app is "owned" if it has been
/// acquired from the Play Store.
/// </summary>
AppNotOwned = 13,
/// <summary>
/// Returned if <see cref="PlayAssetDelivery.ShowConfirmationDialog"/> is called but
/// no asset packs are waiting for user confirmation.
/// </summary>
ConfirmationNotRequired = 14,
/// <summary>
/// Returned if the app was not installed by Play.
/// </summary>
UnrecognizedInstallation = 15,
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 44c7175244a2a4e2fa4c9c0b08ee011a
timeCreated: 1549325947
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,65 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace Google.Play.AssetDelivery
{
/// <summary>
/// Enum indicating the current status of an asset pack request.
/// </summary>
public enum AssetDeliveryStatus
{
/// <summary>
/// Asset pack download is pending and will be processed soon.
/// </summary>
Pending = 0,
/// <summary>
/// Asset pack is being downloaded and transferred to the app's storage.
/// </summary>
Retrieving = 1,
/// <summary>
/// Asset pack is available on disk. For <see cref="PlayAssetPackRequest"/>s this indicates that the request is
/// complete.
/// </summary>
Available = 2,
/// <summary>
/// Contained AssetBundle is being loaded.
/// </summary>
Loading = 3,
/// <summary>
/// Contained AssetBundle has finished loading, assets can now be loaded. For
/// <see cref="PlayAssetBundleRequest"/>s this indicates that the request is complete.
/// </summary>
Loaded = 4,
/// <summary>
/// Asset pack retrieval has failed.
/// </summary>
Failed = 5,
/// <summary>
/// Asset pack download is paused until the device acquires wifi, or the user confirms a dialog
/// presented with <see cref="PlayAssetDelivery.ShowCellularDataConfirmation"/>.
/// </summary>
WaitingForWifi = 6,
/// <summary>
/// Asset pack download is paused until the user provides consent. Consent can be obtained
/// by presenting a dialog with <see cref="PlayAssetDelivery.ShowConfirmationDialog"/>.
RequiresUserConfirmation = 7,
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 25b7a48b8c89b48b689489816a0541ce
timeCreated: 1549325947
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace Google.Play.AssetDelivery
{
/// <summary>
/// Wraps Play Core's AssetLocation which represents the location of an Asset within an asset pack on disk.
/// </summary>
public abstract class AssetLocation
{
/// <summary>
/// If the asset pack is stored within an apk, this will be the path to the APK containing the asset.
/// Otherwise, this will be the path to the specific asset.
/// </summary>
public string Path { get; protected set; }
/// <summary>
/// If the asset pack is stored within an apk this will be the offset of the asset within the APK.
/// Otherwise, this will be 0.
/// </summary>
public ulong Offset { get; protected set; }
/// <summary>
/// If the asset pack is stored within an apk, this will be the size of the asset within the APK.
/// Otherwise, this will be the size of the asset file.
/// </summary>
public ulong Size { get; protected set; }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: feeabbf9c2a5434b92caedf15d713ab4
timeCreated: 1562870112
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,37 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace Google.Play.AssetDelivery
{
/// <summary>
/// Enum indicating the availability of a newer version of a particular asset pack.
/// </summary>
public enum AssetPackUpdateAvailability
{
/// <summary>
/// The asset pack update availability is unknown.
/// </summary>
Unknown = 0,
/// <summary>
/// The asset pack is already at the latest version; there's no update available.
/// </summary>
UpdateNotAvailable = 1,
/// <summary>
/// The asset pack can be updated to a newer version.
/// </summary>
UpdateAvailable = 2
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d5783583a0d44b0ba50a7c506d800d97
timeCreated: 1621898257

View File

@@ -0,0 +1,34 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace Google.Play.AssetDelivery
{
/// <summary>
/// User response to a Play controlled confirmation dialog.
/// </summary>
public enum ConfirmationDialogResult
{
Unknown = 0,
/// <summary>
/// The dialog was confirmed.
/// </summary>
Accepted = 1,
/// <summary>
/// The dialog was cancelled.
/// </summary>
Denied = 2,
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: d76ee58a8b854281a6f86e139807cb9a
timeCreated: 1566422650

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: f4af3441c942f42ce8da4a213cfb959d
folderAsset: yes
timeCreated: 1550267071
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using Google.Play.Common.Internal;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Represents an asynchronous operation that produces a result or an AssetDeliveryErrorCode upon completion.
/// </summary>
/// <typeparam name="TResult">The type of the result of the operation.</typeparam>
internal class AssetDeliveryAsyncOperation<TResult> : PlayAsyncOperationImpl<TResult, AssetDeliveryErrorCode>
{
public override bool IsSuccessful
{
get { return IsDone && Error == AssetDeliveryErrorCode.NoError; }
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 567126ac059a42489a8e5a8a7639dd1c
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,176 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Forwards pack state updates coming from play core.
/// We can't receive updates while the app is in the background, so this MonoBehaviour ensures that pack states
/// are updated when the app enters the foreground.
/// </summary>
internal class AssetDeliveryUpdateHandler : MonoBehaviour
{
public event Action<AssetPackState> OnStateUpdateEvent = delegate { };
/// <summary>
/// The pack names of any AssetBundles that have received state updates after GetPackStates but before the
/// Play Core Task has completed. This is to prevent the race condition between the task returned from
/// <see cref="AssetPackManager.GetPackStates"/> and
/// <see cref="AssetPackStateUpdateListener.OnStateUpdateEvent"/>.
/// </summary>
private readonly HashSet<string> _stateUpdatesSinceGetPackStates = new HashSet<string>();
private bool _gettingPackStates;
private AssetPackStateUpdateListener _stateUpdateListener;
private AssetPackManager _assetPackManager;
private PlayRequestRepository _requestRepository;
public static AssetDeliveryUpdateHandler CreateInScene(AssetPackManager assetPackManager,
PlayRequestRepository requestRepository)
{
var componentHolder = new GameObject();
DontDestroyOnLoad(componentHolder);
componentHolder.name = "AssetDeliveryUpdateHandler";
var instance = componentHolder.AddComponent<AssetDeliveryUpdateHandler>();
instance.Init(assetPackManager, requestRepository);
return instance;
}
private void Init(AssetPackManager assetPackManager, PlayRequestRepository requestRepository)
{
_assetPackManager = assetPackManager;
_requestRepository = requestRepository;
_stateUpdateListener = new AssetPackStateUpdateListener();
_stateUpdateListener.OnStateUpdateEvent += OnStateUpdateReceived;
StartListeningForUpdates();
}
private void Start()
{
if (_assetPackManager == null || _stateUpdateListener == null)
{
throw new InvalidOperationException("AssetDeliveryUpdateHandler was never initialized.");
}
}
private void OnApplicationPause(bool isPaused)
{
if (isPaused)
{
StopListeningForUpdates();
}
else
{
StartListeningForUpdates();
ForcePackStatesUpdate();
}
}
private void OnDestroy()
{
StopListeningForUpdates();
}
/// <summary>
/// Asks <see cref="AssetPackManager"/> for the current pack states and routes them to
/// <see cref="OnForcedStateUpdate"/>.
/// </summary>
private void ForcePackStatesUpdate()
{
if (_gettingPackStates)
{
Debug.LogWarning(
"ForceStateUpdate attempt ignored because the latest states are still being retrieved.");
return;
}
var activeRequestBundleNames = _requestRepository.GetActiveAssetPackNames();
if (activeRequestBundleNames.Length == 0)
{
// No requests to update.
return;
}
BeginGetPackStates();
var getPackStateTask = _assetPackManager.GetPackStates(activeRequestBundleNames);
getPackStateTask.RegisterOnSuccessCallback(ProcessPackStates);
}
/// <summary>
/// Processes a java AssetPackStates object and invokes <see cref="OnForcedStateUpdate"/> for each pack
/// state it contains.
/// </summary>
/// <param name="javaPackStates">A java object representing a AssetPackStates object.</param>
private void ProcessPackStates(AndroidJavaObject javaPackStates)
{
try
{
var packStates = new AssetPackStates(javaPackStates);
foreach (var packStatePair in packStates.PackStates)
{
if (_stateUpdatesSinceGetPackStates.Contains(packStatePair.Key))
{
// A newer state update was received before the getPackStateTask finished.
// Discard this state.
continue;
}
OnStateUpdateEvent.Invoke(packStatePair.Value);
}
}
finally
{
EndGetPackStates();
}
}
private void OnStateUpdateReceived(AssetPackState newState)
{
if (_gettingPackStates)
{
_stateUpdatesSinceGetPackStates.Add(newState.Name);
}
OnStateUpdateEvent.Invoke(newState);
}
private void BeginGetPackStates()
{
_gettingPackStates = true;
}
private void EndGetPackStates()
{
_gettingPackStates = false;
_stateUpdatesSinceGetPackStates.Clear();
}
private void StartListeningForUpdates()
{
_assetPackManager.RegisterListener(_stateUpdateListener);
}
private void StopListeningForUpdates()
{
_assetPackManager.UnregisterListener(_stateUpdateListener);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: bb8fa3dd35e1c4dc790b1faa33b0265c
timeCreated: 1554494584
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,50 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System.Text;
using UnityEngine;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Provides an internal implementation for AssetLocation.
/// </summary>
public class AssetLocationImpl : AssetLocation
{
/// <summary>
/// Creates an AssetPackLocation with all the fields of the underlying Java object, disposing the Java
/// object in the process.
/// </summary>
public AssetLocationImpl(AndroidJavaObject packLocation)
{
using (packLocation)
{
Path = packLocation.Call<string>("path");
// Cast to uint because Unity AssetBundle loading APIs expect uint offset.
Offset = (ulong) packLocation.Call<long>("offset");
Size = (ulong) packLocation.Call<long>("size");
}
}
public override string ToString()
{
var stateDescription = new StringBuilder();
stateDescription.AppendFormat("path: {0}\n", Path);
stateDescription.AppendFormat("offset: {0}\n", Offset);
stateDescription.AppendFormat("size: {0}\n", Size);
return stateDescription.ToString();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 006516d0561e414dbe8a46b07c73c4cc
timeCreated: 1588294051

View File

@@ -0,0 +1,60 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System.Text;
using Google.Play.Core.Internal;
using UnityEngine;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Wraps Play Core's AssetPackLocation which represents the location of an asset pack on disk.
/// </summary>
internal class AssetPackLocation
{
/// <summary>
/// The path to the directory which will contain the contents of an asset pack, if the asset pack is available
/// on disk.
/// </summary>
public string Path { get; private set; }
/// <summary>
/// Returns whether the pack is installed as an APK or unpackaged into a folder on the filesystem.
/// </summary>
public AssetPackStorageMethod PackStorageMethod { get; private set; }
/// <summary>
/// Creates an AssetPackLocation with all the fields of the underlying Java object, disposing the Java
/// object in the process.
/// </summary>
public AssetPackLocation(AndroidJavaObject packLocation)
{
using (packLocation)
{
// Called with AndroidJavaObject instead of string because path may be null.
var javaPathString = packLocation.Call<AndroidJavaObject>("path");
Path = PlayCoreHelper.ConvertJavaString(javaPathString);
PackStorageMethod = (AssetPackStorageMethod) packLocation.Call<int>("packStorageMethod");
}
}
public override string ToString()
{
var stateDescription = new StringBuilder();
stateDescription.AppendFormat("path: {0}\n", Path);
stateDescription.AppendFormat("packStorageMethod: {0}\n", PackStorageMethod);
return stateDescription.ToString();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 5c3389864c64846d9ae474033eba316f
timeCreated: 1554317027
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,223 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using Google.Play.Common;
using Google.Play.Core.Internal;
using UnityEngine;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Wraps Play Core's AssetPackManager which manages downloads of asset packs.
/// </summary>
internal class AssetPackManager : IDisposable
{
private AndroidJavaObject _javaAssetPackManager;
public AssetPackManager()
{
const string factoryClassName = PlayCoreConstants.AssetPackPackagePrefix + "AssetPackManagerFactory";
using (var activity = UnityPlayerHelper.GetCurrentActivity())
using (var assetPackManagerFactory = new AndroidJavaClass(factoryClassName))
{
_javaAssetPackManager = assetPackManagerFactory.CallStatic<AndroidJavaObject>("getInstance", activity);
}
if (_javaAssetPackManager == null)
{
throw new NullReferenceException("Play Core returned null AssetPackManager");
}
}
/// <summary>
/// Registers a listener that will be called when a pack download changes state.
/// Listeners should be subsequently unregistered using <see cref="UnregisterListener"/>
/// </summary>
/// <param name="listener">
/// An AndroidJavaProxy representing a java object of class:
/// com.google.android.play.core.assetpacks.AssetPackStateUpdateListener
/// </param>
public void RegisterListener(AndroidJavaProxy listener)
{
_javaAssetPackManager.Call("registerListener", listener);
}
/// <summary>
/// Calls Play Core to unregister a listener previously added using <see cref="RegisterListener"/>
/// </summary>
/// <param name="listener">
/// An AndroidJavaProxy representing a java object of class:
/// com.google.android.play.core.assetpacks.AssetPackStateUpdateListener
/// </param>
public void UnregisterListener(AndroidJavaProxy listener)
{
_javaAssetPackManager.Call("unregisterListener", listener);
}
/// <summary>
/// Calls Play Core to start a download for the specified asset packs.
/// </summary>
/// <param name="assetPackNames">The asset packs to include in the download request.</param>
/// <returns>
/// A wrapped Play Core task, which will return a AndroidJavaObject representing an
/// AssetPackStates. The caller is responsible for disposing this task.
/// </returns>
public PlayServicesTask<AndroidJavaObject> Fetch(params string[] assetPackNames)
{
using (var request = BuildAssetPackList(assetPackNames))
{
var javaTask = _javaAssetPackManager.Call<AndroidJavaObject>("fetch", request);
return new PlayServicesTask<AndroidJavaObject>(javaTask);
}
}
/// <summary>
/// Calls Play Core to get the states of the specified packs.
/// </summary>
/// <returns>
/// A wrapped Play Core task, which will return a AndroidJavaObject representing an
/// AssetPackStates. The caller is responsible for disposing this task.
/// </returns>
public PlayServicesTask<AndroidJavaObject> GetPackStates(params string[] assetPackNames)
{
using (var packList = BuildAssetPackList(assetPackNames))
{
var javaTask = _javaAssetPackManager.Call<AndroidJavaObject>("getPackStates", packList);
return new PlayServicesTask<AndroidJavaObject>(javaTask);
}
}
/// <summary>
/// Calls Play Core to get the location of the specified asset pack.
/// This should contain the AssetBundle associated with the specified asset pack.
/// </summary>
/// <returns>
/// The AssetPackLocation containing the contents of the specified asset pack, or null if the most up-to-date
/// version of this asset pack isn't available on disk.
/// </returns>
public AssetPackLocation GetPackLocation(string assetPackName)
{
var javaPackLocation = _javaAssetPackManager.Call<AndroidJavaObject>("getPackLocation", assetPackName);
return PlayCoreHelper.IsNull(javaPackLocation) ? null : new AssetPackLocation(javaPackLocation);
}
/// <summary>
/// Calls Play Core to get the location of the specified asset within the specified asset pack.
/// </summary>
/// <returns>
/// The AssetLocation of the specified asset or null if the most up-to-date
/// version of this asset pack isn't available on disk.
/// </returns>
public AssetLocation GetAssetLocation(string assetPackName, string assetPath)
{
var javaAssetLocation =
_javaAssetPackManager.Call<AndroidJavaObject>("getAssetLocation", assetPackName, assetPath);
return PlayCoreHelper.IsNull(javaAssetLocation) ? null : new AssetLocationImpl(javaAssetLocation);
}
/// <summary>
/// Requests to cancel the download for a list of packs.
/// </summary>
/// <returns>
/// Returns a AndroidJavaObject representing an AssetPackStates which contains the new states
/// of all specified assetPackNames.
/// </returns>
public AndroidJavaObject Cancel(params string[] assetPackNames)
{
using (var packList = BuildAssetPackList(assetPackNames))
{
var javaPackStates = _javaAssetPackManager.Call<AndroidJavaObject>("cancel", packList);
return javaPackStates;
}
}
/// <summary>
/// Deletes the specified asset pack from internal storage of the app.
/// Deleted packs will not be re-downloaded after update.
/// If the asset pack is currently being downloaded or installed, this method will not cancel the process.
/// </summary>
/// <returns>
/// A PlayServicesTask representing a Task{Void} that will only be successful if files were successfully
/// deleted.
/// </returns>
public PlayServicesTask<AndroidJavaObject> RemovePack(string assetPackName)
{
var javaTask = _javaAssetPackManager.Call<AndroidJavaObject>("removePack", assetPackName);
return new PlayServicesTask<AndroidJavaObject>(javaTask);
}
/// <summary>
/// Calls Play Core to show a confirmation dialog for all downloads that are currently in the
/// <see cref="AssetDeliveryStatus.WaitingForWifi"/> state. If the user accepts the dialog, then those
/// packs are downloaded over cellular data.
/// </summary>
/// <returns>
/// Returns a <see cref=" PlayServicesTask{ActivityResult}"/> that completes once the dialog has been accepted,
/// denied or closed. A successful task result contains one of the following values:
/// <ul>
/// <li><see cref="ActivityResult.ResultOk"/> if the user accepted.</li>
/// <li><see cref="ActivityResult.ResultCancelled"/> if the user denied or the dialog has been closed in
/// any other way (e.g. backpress).</li>
/// </ul>
/// </returns>
public PlayServicesTask<int> ShowCellularDataConfirmation()
{
var task = _javaAssetPackManager.Call<AndroidJavaObject>("showCellularDataConfirmation",
UnityPlayerHelper.GetCurrentActivity());
return new PlayServicesTask<int>(task);
}
/// <summary>
/// Calls the Java Asset Delivery SDK to show a confirmation dialog for all downloads that
/// are currently in either the <see cref="AssetDeliveryStatus.RequiresUserConfirmation"/>
/// state or the <see cref="AssetDeliveryStatus.WaitingForWifi"/> state.
/// </summary>
/// <returns>
/// Returns a <see cref=" PlayServicesTask{ActivityResult}"/> that completes once the dialog
/// has been accepted, denied or closed. A successful task result contains one of the
/// following values:
/// <ul>
/// <li><see cref="ActivityResult.ResultOk"/> if the user accepted.</li>
/// <li><see cref="ActivityResult.ResultCancelled"/> if the user denied or the dialog has
/// been closed in
/// any other way (e.g. backpress).</li>
/// </ul>
/// </returns>
public PlayServicesTask<int> ShowConfirmationDialog()
{
var task = _javaAssetPackManager.Call<AndroidJavaObject>("showConfirmationDialog",
UnityPlayerHelper.GetCurrentActivity());
return new PlayServicesTask<int>(task);
}
// Returns a list of asset pack names.
private static AndroidJavaObject BuildAssetPackList(params string[] assetPackNames)
{
var assetPackList = new AndroidJavaObject("java.util.ArrayList");
foreach (var packName in assetPackNames)
{
assetPackList.Call<bool>("add", packName);
}
return assetPackList;
}
public void Dispose()
{
_javaAssetPackManager.Dispose();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 04178671ed4954e2bb56c84dd03d92bc
timeCreated: 1549564032
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,78 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System.Text;
using UnityEngine;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Wraps Play Core's AssetPackState which represents the current state of an AssetPack download.
/// </summary>
internal class AssetPackState
{
/// <summary>
/// The name of the asset pack being downloaded.
/// </summary>
public string Name { get; private set; }
/// <summary>
/// The number of bytes downloaded so far.
/// </summary>
public long BytesDownloaded { get; private set; }
/// <summary>
/// The total number of bytes that need to be downloaded.
/// </summary>
public long TotalBytesToDownload { get; private set; }
/// <summary>
/// The status of the associated download session (downloading, downloaded, installed, etc).
/// </summary>
public int Status { get; private set; }
/// <summary>
/// The error code indicating the reason the download session failed.
/// </summary>
public int ErrorCode { get; private set; }
/// <summary>
/// Creates an AssetPackState with all the fields of the underlying Java object, disposing the Java
/// object in the process.
/// </summary>
public AssetPackState(AndroidJavaObject javaAssetPackState)
{
using (javaAssetPackState)
{
Name = javaAssetPackState.Call<string>("name");
BytesDownloaded = javaAssetPackState.Call<long>("bytesDownloaded");
TotalBytesToDownload = javaAssetPackState.Call<long>("totalBytesToDownload");
Status = javaAssetPackState.Call<int>("status");
ErrorCode = javaAssetPackState.Call<int>("errorCode");
}
}
public override string ToString()
{
var stateDescription = new StringBuilder();
stateDescription.AppendFormat("name: {0}\n", Name);
stateDescription.AppendFormat("status: {0}\n", Status);
stateDescription.AppendFormat("error code: {0}\n", ErrorCode);
stateDescription.AppendFormat("bytes downloaded: {0}\n", BytesDownloaded);
stateDescription.AppendFormat("total downloaded: {0}\n", TotalBytesToDownload);
return stateDescription.ToString();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b9528fb96e4de4c618a777a82382ba6e
timeCreated: 1551829374
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,41 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using Google.Play.Core.Internal;
using UnityEngine;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Proxy for Play Core's AssetPackStateUpdateListener class.
/// Used to receive callbacks from Play Core's AssetPackManager.
/// </summary>
internal class AssetPackStateUpdateListener : AndroidJavaProxy
{
public event Action<AssetPackState> OnStateUpdateEvent = delegate { };
public AssetPackStateUpdateListener() :
base(PlayCoreConstants.AssetPackPackagePrefix + "AssetPackStateUpdateListener")
{
}
// Proxied java calls. Method names are camelCase to match the corresponding java methods.
public void onStateUpdate(AndroidJavaObject assetPacksState)
{
var packState = new AssetPackState(assetPacksState);
PlayCoreEventHandler.HandleEvent(() => OnStateUpdateEvent.Invoke(packState));
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d0dc15ad4480243fb8c18279cbae4fa6
timeCreated: 1549327262
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,69 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Google.Play.Core.Internal;
using UnityEngine;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Wraps Play Core's AssetPackStates which represents the current state of all requested asset packs.
/// </summary>
internal class AssetPackStates
{
/// <summary>
/// The total size of all requested packs in bytes.
/// </summary>
public long TotalBytes { get; private set; }
/// <summary>
/// A dictionary containing the download states of all requested asset packs.
/// </summary>
public Dictionary<string, AssetPackState> PackStates { get; private set; }
/// <summary>
/// Creates an AssetPackStates with all the fields of the underlying Java object.
/// </summary>
public AssetPackStates(AndroidJavaObject packStates)
{
using (packStates)
{
TotalBytes = packStates.Call<long>("totalBytes");
PackStates = ConvertPackStatesJavaMapToDictionary(packStates);
}
}
private Dictionary<string, AssetPackState> ConvertPackStatesJavaMapToDictionary(
AndroidJavaObject packStates)
{
using (var javaMap = packStates.Call<AndroidJavaObject>("packStates"))
{
return PlayCoreHelper.ConvertJavaMap<string, AndroidJavaObject>(javaMap)
.ToDictionary(kvp => kvp.Key, kvp => new AssetPackState(kvp.Value));
}
}
public override string ToString()
{
var stateDescription = new StringBuilder();
stateDescription.AppendFormat("total bytes: {0}\n", TotalBytes);
stateDescription.AppendLine("pack names: " + string.Join(", ", PackStates.Keys.ToArray()));
return stateDescription.ToString();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: b31a4c75852ef49b18cecbbae7c55449
timeCreated: 1549325414
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Wraps Play Core's AssetPackLocation which represents the location of an asset pack on disk.
/// </summary>
internal enum AssetPackStorageMethod
{
/// <summary>
/// Indicates that the asset pack is unpackaged into a folder containing individual asset files.
/// Assets contained by this asset pack can be accessed via standard File APIs.
/// </summary>
StorageFiles = 0,
/// <summary>
/// Indicates that the asset pack is installed as APKs containing asset files.
/// Assets contained by this asset pack can be accessed via Asset Manager.
/// </summary>
ApkAssets = 1,
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: bba029dc886c42318f5344e02844a7ea
timeCreated: 1562870321
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,138 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections;
using UnityEngine;
namespace Google.Play.AssetDelivery.Internal
{
internal class PlayAssetBundleRequestImpl : PlayAssetBundleRequest
{
internal readonly PlayAssetPackRequestImpl PackRequest;
private readonly AssetDeliveryUpdateHandler _updateHandler;
private AssetDeliveryStatus _loadingStatus;
private AssetDeliveryErrorCode _loadingError;
public PlayAssetBundleRequestImpl(PlayAssetPackRequestImpl packRequest,
AssetDeliveryUpdateHandler updateHandler)
{
PackRequest = packRequest;
_updateHandler = updateHandler;
_loadingStatus = AssetDeliveryStatus.Pending;
_loadingError = AssetDeliveryErrorCode.NoError;
PackRequest.Completed += OnPackRequestCompleted;
}
public override event Action<PlayAssetBundleRequest> Completed
{
add
{
if (IsDone)
{
value.Invoke(this);
return;
}
base.Completed += value;
}
remove { base.Completed -= value; }
}
public override float DownloadProgress
{
get { return PackRequest.DownloadProgress; }
}
public override AssetDeliveryStatus Status
{
get { return PackRequest.Status == AssetDeliveryStatus.Available ? _loadingStatus : PackRequest.Status; }
}
public override AssetDeliveryErrorCode Error
{
get { return PackRequest.Error == AssetDeliveryErrorCode.NoError ? _loadingError : PackRequest.Error; }
}
private void OnLoadingErrorOccurred(AssetDeliveryErrorCode errorCode)
{
if (IsDone)
{
return;
}
IsDone = true;
_loadingError = errorCode;
_loadingStatus = AssetDeliveryStatus.Failed;
AssetBundle = null;
InvokeCompletedEvent();
}
private void OnLoadingFinished(AssetBundle loadedAssetBundle)
{
if (IsDone)
{
return;
}
DownloadProgress = 1f;
AssetBundle = loadedAssetBundle;
_loadingStatus = AssetDeliveryStatus.Loaded;
IsDone = true;
InvokeCompletedEvent();
}
private void OnPackRequestCompleted(PlayAssetPackRequest packRequest)
{
packRequest.Completed -= OnPackRequestCompleted;
if (packRequest.Error == AssetDeliveryErrorCode.NoError)
{
StartLoadingAssetBundle();
}
else
{
IsDone = true;
InvokeCompletedEvent();
}
}
private void StartLoadingAssetBundle()
{
_updateHandler.StartCoroutine(CoLoadAssetBundle());
DownloadProgress = 1f;
_loadingStatus = AssetDeliveryStatus.Loading;
}
private IEnumerator CoLoadAssetBundle()
{
// Assume that the AssetBundle name equals the asset pack name.
var bundleCreateRequest = PackRequest.LoadAssetBundleAsync(PackRequest.AssetPackName);
yield return bundleCreateRequest;
if (bundleCreateRequest.assetBundle == null)
{
OnLoadingErrorOccurred(AssetDeliveryErrorCode.AssetBundleLoadingError);
yield break;
}
OnLoadingFinished(bundleCreateRequest.assetBundle);
}
public override void AttemptCancel()
{
PackRequest.AttemptCancel();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 2fd44a50730bf4888ac9dfa4416e0a87
timeCreated: 1550014332
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,464 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Google.Play.Common;
using Google.Play.Core.Internal;
using UnityEngine;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Internal implementation of <see cref="PlayAssetDelivery"/> methods.
/// </summary>
internal class PlayAssetDeliveryInternal
{
/// <summary>
/// The subfolder, inside the "assets" directory, into which an asset pack file is stored.
/// This intermediate folder can be useful for targeting (by texture compression format) at build time.
/// </summary>
private const string AssetPackFolderName = "assetpack";
private readonly AssetPackManager _assetPackManager;
private readonly AssetDeliveryUpdateHandler _updateHandler;
private readonly PlayRequestRepository _requestRepository = new PlayRequestRepository();
internal PlayAssetDeliveryInternal()
{
_assetPackManager = new AssetPackManager();
_updateHandler = AssetDeliveryUpdateHandler.CreateInScene(_assetPackManager, _requestRepository);
_updateHandler.OnStateUpdateEvent += ProcessPackStateUpdate;
PlayCoreEventHandler.CreateInScene();
}
internal bool IsDownloaded(string assetBundleName)
{
return _assetPackManager.GetPackLocation(assetBundleName) != null;
}
internal PlayAssetBundleRequest RetrieveAssetBundleAsyncInternal(string assetBundleName)
{
var request = InitializeAssetBundleRequest(assetBundleName);
InitiateRequest(request.PackRequest);
return request;
}
internal PlayAssetBundleRequest RetrieveAssetBundleAsyncInternal(string assetBundleName, bool updateIfAvailable)
{
var request = InitializeAssetBundleRequest(assetBundleName);
InitiateRequest(request.PackRequest, updateIfAvailable);
return request;
}
private PlayAssetBundleRequestImpl InitializeAssetBundleRequest(string assetBundleName)
{
if (_requestRepository.ContainsRequest(assetBundleName))
{
throw new ArgumentException(string.Format("There is already an active request for AssetBundle: {0}",
assetBundleName));
}
var request = CreateAssetBundleRequest(assetBundleName);
_requestRepository.AddAssetBundleRequest(request);
request.Completed += req => _requestRepository.RemoveRequest(assetBundleName);
return request;
}
internal PlayAssetPackRequest RetrieveAssetPackAsyncInternal(string assetPackName)
{
var request = GetExistingAssetPackRequest(assetPackName);
if (request != null)
{
return request;
}
request = InitializeAssetPackRequest(assetPackName);
InitiateRequest(request);
return request;
}
internal PlayAssetPackRequest RetrieveAssetPackAsyncInternal(string assetPackName, bool updateIfAvailable)
{
var request = GetExistingAssetPackRequest(assetPackName);
if (request != null)
{
return request;
}
request = InitializeAssetPackRequest(assetPackName);
InitiateRequest(request, updateIfAvailable);
return request;
}
internal PlayAssetPackBatchRequest RetrieveAssetPackBatchAsyncInternal(IList<string> assetPackNames)
{
return CreateAndInitiateBatchRequest(assetPackNames, IsDownloaded);
}
internal PlayAssetPackBatchRequest RetrieveAssetPackBatchAsyncInternal(IList<string> assetPackNames,
bool updateIfAvailable)
{
Func<string, bool> useAvailablePack = packName => IsCurrentVersionGoodEnough(packName, updateIfAvailable);
return CreateAndInitiateBatchRequest(assetPackNames, useAvailablePack);
}
private PlayAssetPackBatchRequest CreateAndInitiateBatchRequest(IList<string> assetPackNames,
Func<string, bool> isPackAvailable)
{
if (assetPackNames.Count != assetPackNames.Distinct().Count())
{
throw new ArgumentException("assetPackNames contains duplicate entries");
}
var activeAssetBundleRequestNames = assetPackNames
.Where(name => _requestRepository.ContainsAssetBundleRequest(name))
.ToArray();
if (activeAssetBundleRequestNames.Length != 0)
{
throw new ArgumentException("Cannot create a new PlayAssetPackBatchRequests because there are " +
"already PlayAssetBundleRequests for AssetBundles: {0}",
string.Join(", ", activeAssetBundleRequestNames));
}
// A subset of assetPackNames of packs that are not available on disk.
var unavailableAssetPackNames = new List<string>();
var requests = new List<PlayAssetPackRequestImpl>();
foreach (var assetPackName in assetPackNames)
{
PlayAssetPackRequestImpl request;
if (_requestRepository.TryGetRequest(assetPackName, out request))
{
requests.Add(request);
continue;
}
request = CreateAssetPackRequest(assetPackName);
_requestRepository.AddRequest(request);
request.Completed += req => _requestRepository.RemoveRequest(request.AssetPackName);
requests.Add(request);
if (isPackAvailable.Invoke(assetPackName))
{
request.OnPackAvailable();
}
else
{
unavailableAssetPackNames.Add(assetPackName);
}
}
var batchRequest = new PlayAssetPackBatchRequestImpl(requests);
var fetchTask = _assetPackManager.Fetch(unavailableAssetPackNames.ToArray());
fetchTask.RegisterOnSuccessCallback(javaPackStates =>
{
batchRequest.OnInitializedInPlayCore();
fetchTask.Dispose();
});
fetchTask.RegisterOnFailureCallback((reason, errorCode) =>
{
Debug.LogError("Failed to retrieve asset pack batch: " + reason);
batchRequest.OnInitializationErrorOccurred(PlayCoreTranslator.TranslatePlayCoreErrorCode(errorCode));
fetchTask.Dispose();
});
return batchRequest;
}
internal PlayAsyncOperation<ConfirmationDialogResult, AssetDeliveryErrorCode>
ShowCellularDataConfirmationInternal()
{
var requests = _requestRepository.GetRequestsWithStatus(AssetDeliveryStatus.WaitingForWifi);
if (requests.Count == 0)
{
throw new Exception("There are no active requests waiting for wifi.");
}
var task = _assetPackManager.ShowCellularDataConfirmation();
var operation = new AssetDeliveryAsyncOperation<ConfirmationDialogResult>();
task.RegisterOnSuccessCallback(resultCode =>
{
operation.SetResult(ConvertToConfirmationDialogResult(resultCode));
task.Dispose();
});
task.RegisterOnFailureCallback((message, errorCode) =>
{
operation.SetError(PlayCoreTranslator.TranslatePlayCoreErrorCode(errorCode));
task.Dispose();
});
return operation;
}
internal PlayAsyncOperation<ConfirmationDialogResult, AssetDeliveryErrorCode>
ShowConfirmationDialogInternal()
{
var requestsAwaitingWifi = _requestRepository.GetRequestsWithStatus(AssetDeliveryStatus.WaitingForWifi);
var requestsAwaitingConsent = _requestRepository.GetRequestsWithStatus(AssetDeliveryStatus.RequiresUserConfirmation);
if (requestsAwaitingWifi.Count == 0 && requestsAwaitingConsent.Count == 0)
{
throw new Exception("There are no active requests waiting for confirmation.");
}
var task = _assetPackManager.ShowConfirmationDialog();
var operation = new AssetDeliveryAsyncOperation<ConfirmationDialogResult>();
task.RegisterOnSuccessCallback(resultCode =>
{
operation.SetResult(ConvertToConfirmationDialogResult(resultCode));
task.Dispose();
});
task.RegisterOnFailureCallback((message, errorCode) =>
{
operation.SetError(PlayCoreTranslator.TranslatePlayCoreErrorCode(errorCode));
task.Dispose();
});
return operation;
}
internal PlayAsyncOperation<long, AssetDeliveryErrorCode> GetDownloadSizeInternal(string assetBundleName)
{
var operation = new AssetDeliveryAsyncOperation<long>();
if (IsInstallTimeAssetBundle(assetBundleName))
{
operation.SetResult(0L);
return operation;
}
var task = _assetPackManager.GetPackStates(assetBundleName);
task.RegisterOnSuccessCallback(javaPackState =>
{
var assetPacks = new AssetPackStates(javaPackState);
operation.SetResult(assetPacks.TotalBytes);
task.Dispose();
});
task.RegisterOnFailureCallback((message, errorCode) =>
{
operation.SetError(PlayCoreTranslator.TranslatePlayCoreErrorCode(errorCode));
task.Dispose();
});
return operation;
}
internal PlayAsyncOperation<IDictionary<string, PlayAssetPackDownloadInfo>, AssetDeliveryErrorCode>
GetDownloadInfoInternal(IList<string> assetPackNames)
{
var operation = new AssetDeliveryAsyncOperation<IDictionary<string, PlayAssetPackDownloadInfo>>();
var task = _assetPackManager.GetPackStates(assetPackNames.ToArray());
task.RegisterOnSuccessCallback(javaPackStates =>
{
operation.SetResult(PlayAssetPackDownloadInfoImpl.FromAssetPackStates(javaPackStates));
task.Dispose();
});
task.RegisterOnFailureCallback((message, errorCode) =>
{
operation.SetError(PlayCoreTranslator.TranslatePlayCoreErrorCode(errorCode));
task.Dispose();
});
return operation;
}
internal PlayAsyncOperation<VoidResult, AssetDeliveryErrorCode> RemoveAssetPackInternal(
string assetBundleName)
{
var operation = new AssetDeliveryAsyncOperation<VoidResult>();
var task = _assetPackManager.RemovePack(assetBundleName);
task.RegisterOnSuccessCallback(javaPackState =>
{
operation.SetResult(new VoidResult());
task.Dispose();
});
task.RegisterOnFailureCallback((message, errorCode) =>
{
operation.SetError(AssetDeliveryErrorCode.InternalError);
task.Dispose();
});
return operation;
}
private AssetLocation GetAssetLocation(string assetBundleName)
{
var assetPath = Path.Combine(AssetPackFolderName, assetBundleName);
return _assetPackManager.GetAssetLocation(assetBundleName, assetPath);
}
private PlayAssetPackRequestImpl GetExistingAssetPackRequest(string assetPackName)
{
if (_requestRepository.ContainsAssetBundleRequest(assetPackName))
{
throw new ArgumentException(string.Format(
"Cannot create a new PlayAssetPackRequest because there is already an active " +
"PlayAssetBundleRequest for asset bundle: {0}",
assetPackName));
}
PlayAssetPackRequestImpl request;
if (_requestRepository.TryGetRequest(assetPackName, out request))
{
Debug.Log("Returning existing active request for " + assetPackName);
}
return request;
}
private PlayAssetPackRequestImpl InitializeAssetPackRequest(string assetPackName)
{
var request = CreateAssetPackRequest(assetPackName);
_requestRepository.AddRequest(request);
request.Completed += req => _requestRepository.RemoveRequest(assetPackName);
return request;
}
private PlayAssetPackRequestImpl CreateAssetPackRequest(string assetPackName)
{
return new PlayAssetPackRequestImpl(assetPackName, _assetPackManager, _requestRepository);
}
private PlayAssetBundleRequestImpl CreateAssetBundleRequest(string assetBundleName)
{
var packRequest = CreateAssetPackRequest(assetBundleName);
return new PlayAssetBundleRequestImpl(packRequest, _updateHandler);
}
private void InitiateRequest(PlayAssetPackRequestImpl request)
{
StartRequest(request, IsDownloaded(request.AssetPackName));
}
private void InitiateRequest(PlayAssetPackRequestImpl request, bool updateIfAvailable)
{
StartRequest(request, IsCurrentVersionGoodEnough(request.AssetPackName, updateIfAvailable));
}
private bool IsCurrentVersionGoodEnough(string assetPackName, bool wantNewerVersion)
{
var packLocation = _assetPackManager.GetPackLocation(assetPackName);
bool isCurrentVersionGoodEnough;
if (packLocation == null)
{
isCurrentVersionGoodEnough= false;
}
else if (packLocation.PackStorageMethod == AssetPackStorageMethod.ApkAssets)
{
// If the pack exists as an APK, then it is an install-time pack which cannot be updated.
isCurrentVersionGoodEnough = true;
}
else
{
// When wantNewerVersion is true,
// we can't use the version on disk without checking if a newer version exists.
isCurrentVersionGoodEnough = !wantNewerVersion;
}
return isCurrentVersionGoodEnough;
}
private void StartRequest(PlayAssetPackRequestImpl request, bool isAvailable)
{
if (isAvailable)
{
request.OnPackAvailable();
}
else
{
var fetchTask = _assetPackManager.Fetch(request.AssetPackName);
fetchTask.RegisterOnSuccessCallback(javaPackStates =>
{
request.OnInitializedInPlayCore();
fetchTask.Dispose();
});
fetchTask.RegisterOnFailureCallback((reason, errorCode) =>
{
Debug.LogErrorFormat("Failed to retrieve asset pack: {0}", reason);
request.OnErrorOccured(PlayCoreTranslator.TranslatePlayCoreErrorCode(errorCode));
fetchTask.Dispose();
});
}
}
private void ProcessPackStateUpdate(AssetPackState newState)
{
PlayAssetPackRequestImpl request;
if (!_requestRepository.TryGetRequest(newState.Name, out request))
{
Debug.LogWarningFormat(
"Received state update \"{0}\", that is not associated with an active request.",
newState.Name);
return;
}
UpdateRequest(request, newState, newState.ErrorCode);
}
private void UpdateRequest(PlayAssetPackRequestImpl request, AssetPackState newState, int errorCode)
{
if (request.IsDone)
{
// Ignore pack state updates associated with completed requests.
return;
}
var assetDeliveryErrorCode = PlayCoreTranslator.TranslatePlayCoreErrorCode(errorCode);
if (assetDeliveryErrorCode != AssetDeliveryErrorCode.NoError)
{
request.OnErrorOccured(assetDeliveryErrorCode);
return;
}
if (newState.Status == PlayCoreTranslator.AssetPackStatus.Canceled)
{
request.OnErrorOccured(AssetDeliveryErrorCode.Canceled);
return;
}
request.UpdateState(PlayCoreTranslator.TranslatePlayCorePackStatus(newState.Status),
newState.BytesDownloaded,
newState.TotalBytesToDownload);
}
private bool IsInstallTimeAssetBundle(string assetBundleName)
{
var packLocation = _assetPackManager.GetPackLocation(assetBundleName);
return packLocation != null && packLocation.PackStorageMethod == AssetPackStorageMethod.ApkAssets;
}
private ConfirmationDialogResult ConvertToConfirmationDialogResult(int resultCode)
{
ConfirmationDialogResult dialogResult;
switch (resultCode)
{
case ActivityResult.ResultOk:
dialogResult = ConfirmationDialogResult.Accepted;
break;
case ActivityResult.ResultCancelled:
dialogResult = ConfirmationDialogResult.Denied;
break;
default:
throw new NotImplementedException("Unexpected activity result: " + resultCode);
}
return dialogResult;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 85b7e6bf8e3e4b8e91cbb5716761c9ed
timeCreated: 1583540802

View File

@@ -0,0 +1,95 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
using System.Linq;
namespace Google.Play.AssetDelivery.Internal
{
public class PlayAssetPackBatchRequestImpl : PlayAssetPackBatchRequest
{
private readonly HashSet<string> _completedPackNames = new HashSet<string>();
internal PlayAssetPackBatchRequestImpl(IEnumerable<PlayAssetPackRequestImpl> requests)
{
Requests = requests.ToDictionary(request => request.AssetPackName,
request => request as PlayAssetPackRequest);
foreach (var entry in Requests)
{
entry.Value.Completed += OnChildPackCompleted;
}
}
public override event Action<PlayAssetPackBatchRequest> Completed
{
add
{
if (IsDone)
{
value.Invoke(this);
return;
}
base.Completed += value;
}
remove { base.Completed -= value; }
}
public void OnInitializedInPlayCore()
{
foreach (var request in Requests.Values)
{
var requestImpl = request as PlayAssetPackRequestImpl;
if (requestImpl == null)
{
throw new ArgumentException("Request is not a PlayAssetPackRequestImpl");
}
requestImpl.OnInitializedInPlayCore();
}
}
public void OnInitializationErrorOccurred(AssetDeliveryErrorCode errorCode)
{
foreach (var request in Requests.Values)
{
var requestImpl = request as PlayAssetPackRequestImpl;
if (requestImpl == null)
{
throw new ArgumentException("Request is not a PlayAssetPackRequestImpl");
}
requestImpl.OnErrorOccured(errorCode);
}
}
private void OnChildPackCompleted(PlayAssetPackRequest request)
{
var requestImpl = request as PlayAssetPackRequestImpl;
if (requestImpl == null)
{
throw new ArgumentException("Request is not a PlayAssetPackRequestImpl");
}
_completedPackNames.Add(requestImpl.AssetPackName);
if (_completedPackNames.Count == Requests.Count && !IsDone)
{
IsDone = true;
InvokeCompletedEvent();
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: a740d87a2bf1401bb24681935998ecd7
timeCreated: 1588812080

View File

@@ -0,0 +1,81 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Google.Play.Core.Internal;
using UnityEngine;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Wraps the subset of Play Core's AssetPackState that pertains to asset-only updates.
/// It contains information regarding newer versions of a particular asset pack.
/// </summary>
public class PlayAssetPackDownloadInfoImpl : PlayAssetPackDownloadInfo
{
/// <summary>
/// Creates a dictionary with download info, keyed by asset pack name, from the asset packs contained within a PlayCore
/// AssetPackStates object.
/// </summary>
/// <param name="javaAssetPackStates">
/// The PlayCore AssetPacksStates object containing the desired asset pack info.
/// </param>
/// <returns>
/// A dictionary, keyed by asset pack name, containing download info about the packs within the specified
/// AssetPackStates.
/// </returns>
public static IDictionary<string, PlayAssetPackDownloadInfo> FromAssetPackStates(
AndroidJavaObject javaAssetPackStates)
{
using (var javaMap = javaAssetPackStates.Call<AndroidJavaObject>("packStates"))
{
return PlayCoreHelper.ConvertJavaMap<string, AndroidJavaObject>(javaMap)
.ToDictionary<KeyValuePair<string, AndroidJavaObject>, string, PlayAssetPackDownloadInfo>(
kvp => kvp.Key,
kvp => new PlayAssetPackDownloadInfoImpl(kvp.Value));
}
}
/// <summary>
/// Creates a PlayAssetPackDownloadInfoImpl from the underlying Java AssetPackState.
/// Disposes the Java object in the process.
/// </summary>
/// <param name="javaAssetPackState">
/// The PlayCore AssetPackState Java object from which to create the PlayAssetPackDownloadInfoImpl.
/// </param>
public PlayAssetPackDownloadInfoImpl(AndroidJavaObject javaAssetPackState)
{
var javaAvailability = javaAssetPackState.Call<int>("updateAvailability");
UpdateAvailability = UpdateAvailabilityTranslator.TranslatePlayCoreUpdateAvailability(javaAvailability);
DownloadSize = javaAssetPackState.Call<long>("totalBytesToDownload");
AvailableVersionTag = javaAssetPackState.Call<string>("availableVersionTag");
InstalledVersionTag = javaAssetPackState.Call<string>("installedVersionTag");
javaAssetPackState.Dispose();
}
public override string ToString()
{
var stateDescription = new StringBuilder();
stateDescription.AppendFormat("update availability: {0}\n", UpdateAvailability);
stateDescription.AppendFormat("available version tag: {0}\n", AvailableVersionTag);
stateDescription.AppendFormat("installed version tag: {0}\n", InstalledVersionTag);
return stateDescription.ToString();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c3b4bb5ea9d44aa4a75c9cebdf74dc78
timeCreated: 1621899620

View File

@@ -0,0 +1,183 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.IO;
using Google.Play.Core.Internal;
using UnityEngine;
namespace Google.Play.AssetDelivery.Internal
{
internal class PlayAssetPackRequestImpl : PlayAssetPackRequest
{
public readonly string AssetPackName;
/// <summary>
/// The name of the folder within an asset pack containing all the pack's assets.
/// Asset packs packaged using the Unity packaging API will place all their assets under this folder.
/// </summary>
private const string AssetPackFolderName = "assetpack";
private readonly AssetPackManager _assetPackManager;
private bool _initializedInPlayCore;
private readonly PlayRequestRepository _requestRepository;
private Action _onInitializedInPlayCore = delegate { };
public PlayAssetPackRequestImpl(string assetPackName, AssetPackManager assetPackManager,
PlayRequestRepository requestRepository)
{
AssetPackName = assetPackName;
_assetPackManager = assetPackManager;
_requestRepository = requestRepository;
}
public override event Action<PlayAssetPackRequest> Completed
{
add
{
if (IsDone)
{
value.Invoke(this);
return;
}
base.Completed += value;
}
remove { base.Completed -= value; }
}
public void UpdateState(AssetDeliveryStatus status, long bytesDownloaded, long totalBytesToDownload)
{
if (totalBytesToDownload == 0L)
{
bool finishedDownloading = status == AssetDeliveryStatus.Available
|| status == AssetDeliveryStatus.Loading
|| status == AssetDeliveryStatus.Loaded;
DownloadProgress = finishedDownloading ? 1f : 0f;
}
else
{
DownloadProgress = bytesDownloaded / (float) totalBytesToDownload;
}
Status = status;
if (Status == AssetDeliveryStatus.Available)
{
OnPackAvailable();
}
}
public void OnInitializedInPlayCore()
{
// Execute on the main thread in case _onInitializedInPlayCore needs to check _requestRepository.
PlayCoreEventHandler.HandleEvent(() =>
{
_initializedInPlayCore = true;
_onInitializedInPlayCore();
});
}
public void OnPackAvailable()
{
Status = AssetDeliveryStatus.Available;
DownloadProgress = 1f;
if (!IsDone)
{
IsDone = true;
InvokeCompletedEvent();
}
}
public void OnErrorOccured(AssetDeliveryErrorCode errorCode)
{
if (IsDone)
{
return;
}
IsDone = true;
Error = errorCode;
Status = AssetDeliveryStatus.Failed;
InvokeCompletedEvent();
}
public override AssetBundleCreateRequest LoadAssetBundleAsync(string assetBundlePath)
{
var assetLocation = GetAssetLocation(assetBundlePath);
if (assetLocation == null)
{
// Check if the assetBundlePath was relative to "assets" path rather than to the "assets/assetpack"
// path. This may be a common error, so we check for it here and warn the developer.
if (AssetPackFolderName.Equals(assetBundlePath.Split('/')[0]))
{
Debug.LogError("Failed to find the asset at path {0} within the asset pack, possibly because the" +
" path begins with \"assetpack\".");
}
return null;
}
return AssetBundle.LoadFromFileAsync(assetLocation.Path, /* crc= */ 0, assetLocation.Offset);
}
public override AssetLocation GetAssetLocation(string assetPath)
{
var fullAssetPath = Path.Combine(AssetPackFolderName, assetPath);
return _assetPackManager.GetAssetLocation(AssetPackName, fullAssetPath);
}
public override void AttemptCancel()
{
if (IsDone || Status == AssetDeliveryStatus.Loaded)
{
return;
}
// If play core is aware of the associated pack, then we tell play core to cancel the pack download.
// Otherwise, we notify play core after the fetch task succeeds.
if (_initializedInPlayCore)
{
CancelPlayCore();
}
else
{
DeferCancelPlayCore();
}
OnErrorOccured(AssetDeliveryErrorCode.Canceled);
}
private void CancelPlayCore()
{
_assetPackManager.Cancel(AssetPackName).Dispose();
}
private void DeferCancelPlayCore()
{
_onInitializedInPlayCore = () =>
{
// Only cancel if a new request hasn't been started, to avoid cancelling the new request.
if (_requestRepository.ContainsRequest(AssetPackName))
{
Debug.LogFormat("Skip canceling {0}", AssetPackName);
}
else
{
CancelPlayCore();
}
};
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 24b88ac66b804124b880ad0b6b6f2dcc
timeCreated: 1588102816

View File

@@ -0,0 +1,131 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Translates PlayCore's AssetPackErrorCode and AssetPackStatus Java enums into their corresponding public-facing
/// Unity enums.
/// </summary>
internal static class PlayCoreTranslator
{
private static class AssetPackErrorCode
{
public const int NoError = 0;
public const int AppUnavailable = -1;
public const int PackUnavailable = -2;
public const int InvalidRequest = -3;
public const int DownloadNotFound = -4;
public const int ApiNotAvailable = -5;
public const int NetworkError = -6;
public const int AccessDenied = -7;
public const int InsufficientStorage = -10;
public const int PlayStoreNotFound = -11;
public const int NetworkUnrestricted = -12;
public const int AppNotOwned = -13;
public const int ConfirmationNotRequired = -14;
public const int UnrecognizedInstallation = -15;
public const int InternalError = -100;
}
public static class AssetPackStatus
{
public const int Unknown = 0;
public const int Pending = 1;
public const int Downloading = 2;
public const int Transferring = 3;
public const int Completed = 4;
public const int Failed = 5;
public const int Canceled = 6;
public const int WaitingForWifi = 7;
public const int NotInstalled = 8;
public const int RequiresUserConfirmation = 9;
}
private static readonly Dictionary<int, AssetDeliveryErrorCode> PlayCoreToAssetDeliveryErrors =
new Dictionary<int, AssetDeliveryErrorCode>
{
{AssetPackErrorCode.NoError, AssetDeliveryErrorCode.NoError},
{AssetPackErrorCode.AppUnavailable, AssetDeliveryErrorCode.AppUnavailable},
{AssetPackErrorCode.PackUnavailable, AssetDeliveryErrorCode.BundleUnavailable},
{AssetPackErrorCode.InvalidRequest, AssetDeliveryErrorCode.InternalError},
{AssetPackErrorCode.ApiNotAvailable, AssetDeliveryErrorCode.InternalError},
{AssetPackErrorCode.DownloadNotFound, AssetDeliveryErrorCode.InternalError},
{AssetPackErrorCode.InternalError, AssetDeliveryErrorCode.InternalError},
{AssetPackErrorCode.NetworkError, AssetDeliveryErrorCode.NetworkError},
{AssetPackErrorCode.AccessDenied, AssetDeliveryErrorCode.AccessDenied},
{AssetPackErrorCode.InsufficientStorage, AssetDeliveryErrorCode.InsufficientStorage},
{AssetPackErrorCode.PlayStoreNotFound, AssetDeliveryErrorCode.PlayStoreNotFound},
{AssetPackErrorCode.NetworkUnrestricted, AssetDeliveryErrorCode.NetworkUnrestricted},
{AssetPackErrorCode.AppNotOwned, AssetDeliveryErrorCode.AppNotOwned},
{AssetPackErrorCode.ConfirmationNotRequired, AssetDeliveryErrorCode.ConfirmationNotRequired},
{AssetPackErrorCode.UnrecognizedInstallation, AssetDeliveryErrorCode.UnrecognizedInstallation},
};
private static readonly Dictionary<int, AssetDeliveryStatus> PlayCoreToAssetDeliveryStatuses
=
new Dictionary<int, AssetDeliveryStatus>
{
// Unity Asset Delivery requests are started immediately, so their status is Pending even if play core
// has not yet set its status to Pending.
{AssetPackStatus.NotInstalled, AssetDeliveryStatus.Pending},
{AssetPackStatus.Pending, AssetDeliveryStatus.Pending},
{AssetPackStatus.Downloading, AssetDeliveryStatus.Retrieving},
{AssetPackStatus.Transferring, AssetDeliveryStatus.Retrieving},
{AssetPackStatus.Completed, AssetDeliveryStatus.Available},
{AssetPackStatus.WaitingForWifi, AssetDeliveryStatus.WaitingForWifi},
{AssetPackStatus.RequiresUserConfirmation, AssetDeliveryStatus.RequiresUserConfirmation},
{AssetPackStatus.Failed, AssetDeliveryStatus.Failed},
{AssetPackStatus.Unknown, AssetDeliveryStatus.Failed},
{AssetPackStatus.Canceled, AssetDeliveryStatus.Failed},
};
/// <summary>
/// Translates Play Core's AssetPackErrorCode into its corresponding public-facing AssetDeliveryErrorCode.
/// </summary>
/// <exception cref="NotImplementedException">
/// Throws if the provided error code does not have a corresponding value in AssetDeliveryErrorCode.
/// </exception>
public static AssetDeliveryErrorCode TranslatePlayCoreErrorCode(int assetPackErrorCode)
{
AssetDeliveryErrorCode translatedErrorCode;
if (!PlayCoreToAssetDeliveryErrors.TryGetValue(assetPackErrorCode, out translatedErrorCode))
{
throw new NotImplementedException("Unexpected error code: " + assetPackErrorCode);
}
return translatedErrorCode;
}
/// <summary>
/// Translates Play Core's AssetPackStatus into its corresponding public-facing AssetDeliveryStatus.
/// </summary>
/// <exception cref="NotImplementedException">
/// Throws if the provided status does not have a corresponding value in AssetDeliveryStatus.
/// </exception>
public static AssetDeliveryStatus TranslatePlayCorePackStatus(int assetPackStatus)
{
AssetDeliveryStatus translatedStatus;
if (!PlayCoreToAssetDeliveryStatuses.TryGetValue(assetPackStatus, out translatedStatus))
{
throw new NotImplementedException("Unexpected pack status: " + assetPackStatus);
}
return translatedStatus;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 560fb67e8b05948c8aa0b6314480534d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,86 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System.Collections.Generic;
using System.Linq;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Repository for active requests related to Play Asset Delivery.
/// </summary>
internal class PlayRequestRepository
{
/// <summary>
/// Contains all active requests, including the <see cref="PlayAssetPackRequestImpl"/> contained within active
/// <see cref="PlayAssetBundleRequestImpl"/>.
/// </summary>
private Dictionary<string, PlayAssetPackRequestImpl> _requestsByName =
new Dictionary<string, PlayAssetPackRequestImpl>();
/// <summary>
/// Contains all active asset bundle requests. Every entry should have a corresponding entry in _requestsByName
/// for assetBundleRequest.PackRequest.
/// </summary>
private Dictionary<string, PlayAssetBundleRequestImpl> _assetBundleRequestsByName =
new Dictionary<string, PlayAssetBundleRequestImpl>();
public void AddAssetBundleRequest(PlayAssetBundleRequestImpl assetBundleRequest)
{
AddRequest(assetBundleRequest.PackRequest);
_assetBundleRequestsByName.Add(assetBundleRequest.PackRequest.AssetPackName, assetBundleRequest);
}
public void AddRequest(PlayAssetPackRequestImpl request)
{
_requestsByName.Add(request.AssetPackName, request);
}
public void RemoveRequest(string name)
{
_requestsByName.Remove(name);
_assetBundleRequestsByName.Remove(name);
}
public bool TryGetAssetBundleRequest(string name, out PlayAssetBundleRequestImpl assetBundleRequest)
{
return _assetBundleRequestsByName.TryGetValue(name, out assetBundleRequest);
}
public bool TryGetRequest(string name, out PlayAssetPackRequestImpl request)
{
return _requestsByName.TryGetValue(name, out request);
}
public IList<PlayAssetPackRequestImpl> GetRequestsWithStatus(AssetDeliveryStatus status)
{
return _requestsByName.Values.Where(request => request.Status == status).ToList();
}
public string[] GetActiveAssetPackNames()
{
return _requestsByName.Keys.ToArray();
}
public bool ContainsAssetBundleRequest(string name)
{
return _assetBundleRequestsByName.ContainsKey(name);
}
public bool ContainsRequest(string name)
{
return _requestsByName.ContainsKey(name);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9d8abdc8cf0340bbaae418da558de978
timeCreated: 1558390718

View File

@@ -0,0 +1,65 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
namespace Google.Play.AssetDelivery.Internal
{
/// <summary>
/// Translates PlayCore's AssetPackUpdateAvailability Java enum into its corresponding public-facing
/// Unity enum.
/// </summary>
internal class UpdateAvailabilityTranslator
{
private static class PlayCoreAssetPackUpdateAvailability
{
public const int Unknown = 0;
public const int UpdateNotAvailable = 1;
public const int UpdateAvailable = 2;
}
private static readonly Dictionary<int, AssetPackUpdateAvailability> PlayCoreToAssetPackUpdateAvailability
=
new Dictionary<int, AssetPackUpdateAvailability>
{
{PlayCoreAssetPackUpdateAvailability.Unknown, AssetPackUpdateAvailability.Unknown},
{
PlayCoreAssetPackUpdateAvailability.UpdateNotAvailable,
AssetPackUpdateAvailability.UpdateNotAvailable
},
{PlayCoreAssetPackUpdateAvailability.UpdateAvailable, AssetPackUpdateAvailability.UpdateAvailable},
};
/// <summary>
/// Translates Play Core's AssetPackUpdateAvailability into its corresponding public-facing AssetPackUpdateAvailability.
/// </summary>
/// <exception cref="NotImplementedException">
/// Throws if the provided update availability does not have a corresponding value in AssetPackUpdateAvailability.
/// </exception>
public static AssetPackUpdateAvailability TranslatePlayCoreUpdateAvailability(
int assetPackUpdateAvailability)
{
AssetPackUpdateAvailability translatedAvailability;
if (!PlayCoreToAssetPackUpdateAvailability.TryGetValue(assetPackUpdateAvailability,
out translatedAvailability))
{
throw new NotImplementedException("Unexpected pack update availability: " +
assetPackUpdateAvailability);
}
return translatedAvailability;
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 686aee5c471041bba8bfb766b774885d
timeCreated: 1621899159

View File

@@ -0,0 +1,92 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using UnityEngine;
namespace Google.Play.AssetDelivery
{
/// <summary>
/// A <a href="https://docs.unity3d.com/ScriptReference/CustomYieldInstruction.html">CustomYieldInstruction</a>
/// used to monitor the asynchronous retrieval of an asset pack containing an AssetBundle.
/// </summary>
public abstract class PlayAssetBundleRequest : CustomYieldInstruction
{
/// <summary>
/// Progress between 0 and 1 indicating the overall download progress of this request.
///
/// Note: If this value is equal to 1, it does not mean that the request has completed,
/// only that the Downloading stage is finished.
/// </summary>
public virtual float DownloadProgress { get; protected set; }
/// <summary>
/// The error that prevented this requested from completing successfully.
/// In the case of a successful request, this will always be <see cref="AssetDeliveryErrorCode.NoError"/>.
/// </summary>
public virtual AssetDeliveryErrorCode Error { get; protected set; }
/// <summary>
/// Returns true if this request is in the <see cref="AssetDeliveryStatus.Loaded"/> or
/// <see cref="AssetDeliveryStatus.Failed"/> status, false otherwise.
/// </summary>
public bool IsDone { get; protected set; }
/// <summary>
/// An enum indicating the status of this request (downloading, downloaded, installed etc.)
/// If the request completed successfully, this value should be <see cref="AssetDeliveryStatus.Loaded"/>.
/// If an error occured, it should be <see cref="AssetDeliveryStatus.Failed"/>.
/// </summary>
public virtual AssetDeliveryStatus Status { get; protected set; }
/// <summary>
/// The AssetBundle loaded by this request.
/// This corresponds to the AssetBundle name passed into this request.
/// If Status is not <see cref="AssetDeliveryStatus.Loaded"/>, this value is null.
/// </summary>
public AssetBundle AssetBundle { get; protected set; }
/// <summary>
/// Event indicating that the request is completed. If an event handler is registered after the operation has
/// completed, and thus after this event has been invoked, then the handler will be called synchronously.
/// </summary>
public virtual event Action<PlayAssetBundleRequest> Completed = delegate { };
/// <summary>
/// Implements the <a href="https://docs.unity3d.com/ScriptReference/CustomYieldInstruction-keepWaiting.html">CustomYieldInstruction.keepWaiting</a>
/// property so that this request can be yielded on in a coroutine.
/// </summary>
public override bool keepWaiting
{
get { return !IsDone; }
}
/// <summary>
/// Cancels the request if possible, setting Status to <see cref="AssetDeliveryStatus.Failed"/> and
/// Error to <see cref="AssetDeliveryErrorCode.Canceled"/>.
/// If the request is already <see cref="AssetDeliveryStatus.Loading"/>,
/// <see cref="AssetDeliveryStatus.Loaded"/> or <see cref="AssetDeliveryStatus.Failed"/>, then
/// the request is left unchanged.
/// </summary>
public abstract void AttemptCancel();
/// <summary>
/// Invokes the <see cref="Completed"/> event.
/// </summary>
protected void InvokeCompletedEvent()
{
Completed.Invoke(this);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 3d2ce5aab689a45c3afaba25494614a9
timeCreated: 1548720072
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,248 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
using Google.Play.AssetDelivery.Internal;
using Google.Play.Common;
namespace Google.Play.AssetDelivery
{
/// <summary>
/// Provides methods for retrieving asset packs via the Play Asset Delivery system.
/// </summary>
public static class PlayAssetDelivery
{
private static PlayAssetDeliveryInternal _instance;
private static PlayAssetDeliveryInternal Instance
{
get { return _instance ?? (_instance = new PlayAssetDeliveryInternal()); }
}
/// <summary>
/// Returns whether or not the specified asset pack is available on disk.
/// </summary>
/// <param name="assetPackName">The name of the desired asset pack.</param>
/// <returns>True if the asset pack is available on disk and false if not.</returns>
public static bool IsDownloaded(string assetPackName)
{
return Instance.IsDownloaded(assetPackName);
}
/// <summary>
/// Starts a <see cref="PlayAssetBundleRequest"/> to retrieve an asset pack containing only
/// the specified AssetBundle.
/// Both the AssetBundle and asset pack must share the same name. Downloads the asset pack if
/// it isn't already available on disk.
///
/// After download, the contained AssetBundle is loaded into memory before the request completes.
/// </summary>
/// <param name="assetBundleName">The name of the requested AssetBundle.</param>
/// <returns>A request object used to monitor the asynchronous AssetBundle retrieval.</returns>
/// <exception cref="ArgumentException">
/// Thrown if there is already an active request with the specified name.
/// </exception>
public static PlayAssetBundleRequest RetrieveAssetBundleAsync(string assetBundleName)
{
return Instance.RetrieveAssetBundleAsyncInternal(assetBundleName);
}
/// <summary>
/// Starts a <see cref="PlayAssetBundleRequest"/> to retrieve an asset pack containing only
/// the specified AssetBundle.
/// Both the AssetBundle and asset pack must share the same name. Downloads the asset pack if
/// it isn't already available on disk.
///
/// After download, the contained AssetBundle is loaded into memory before the request completes.
/// </summary>
/// <param name="assetBundleName">The name of the requested AssetBundle.</param>
/// <param name="updateIfAvailable">
/// If true and the specified pack is already installed,
/// this method will check for a newer version and download it if available.
/// </param>
/// <returns>A request object used to monitor the asynchronous AssetBundle retrieval.</returns>
/// <exception cref="ArgumentException">
/// Thrown if there is already an active request with the specified name.
/// </exception>
public static PlayAssetBundleRequest RetrieveAssetBundleAsync(string assetBundleName, bool updateIfAvailable)
{
return Instance.RetrieveAssetBundleAsyncInternal(assetBundleName, updateIfAvailable);
}
/// <summary>
/// Starts a <see cref="PlayAssetPackRequest"/> to retrieve the specified asset pack.
/// Downloads the asset pack if it isn't already available on disk.
///
/// After download, the assets and/or AssetBundles contained in the asset pack are <b>not</b>
/// loaded into memory. To load them see <see cref="PlayAssetPackRequest.GetAssetLocation"/>
/// or <see cref="PlayAssetPackRequest.LoadAssetBundleAsync"/>.
/// </summary>
/// <param name="assetPackName">The name of the requested asset pack.</param>
/// <returns>A request object used to monitor the asynchronous asset pack retrieval.</returns>
public static PlayAssetPackRequest RetrieveAssetPackAsync(string assetPackName)
{
return Instance.RetrieveAssetPackAsyncInternal(assetPackName);
}
/// <summary>
/// Starts a <see cref="PlayAssetPackRequest"/> to retrieve the specified asset pack.
/// Downloads the asset pack if it isn't already available on disk.
///
/// After download, the assets and/or AssetBundles contained in the asset pack are <b>not</b>
/// loaded into memory. To load them see <see cref="PlayAssetPackRequest.GetAssetLocation"/>
/// or <see cref="PlayAssetPackRequest.LoadAssetBundleAsync"/>.
/// </summary>
/// <param name="assetPackName">The name of the requested asset pack.</param>
/// <param name="updateIfAvailable">
/// If true and the specified pack is already installed,
/// this method will check for a newer version and download it if available.
/// </param>
/// <returns>A request object used to monitor the asynchronous asset pack retrieval.</returns>
public static PlayAssetPackRequest RetrieveAssetPackAsync(string assetPackName, bool updateIfAvailable)
{
return Instance.RetrieveAssetPackAsyncInternal(assetPackName, updateIfAvailable);
}
/// <summary>
/// Starts a <see cref="PlayAssetPackBatchRequest"/> to retrieve the specified asset packs.
/// Downloads the asset packs if they aren't already available on disk.
///
/// After download, the assets and/or AssetBundles contained in the asset pack are <b>not</b>
/// loaded into memory. To load them use <see cref="PlayAssetPackRequest.GetAssetLocation"/>
/// or <see cref="PlayAssetPackRequest.LoadAssetBundleAsync"/> on the values of the
/// <see cref="PlayAssetPackBatchRequest.Requests"/> dictionary.
/// </summary>
/// <param name="assetPackNames">A list of requested asset packs.</param>
/// <returns>A request object used to monitor the asynchronous asset pack batch retrieval.</returns>
/// <exception cref="ArgumentException">Throws if assetPackNames contains duplicate entries.</exception>
public static PlayAssetPackBatchRequest RetrieveAssetPackBatchAsync(IList<string> assetPackNames)
{
return Instance.RetrieveAssetPackBatchAsyncInternal(assetPackNames);
}
/// <summary>
/// Starts a <see cref="PlayAssetPackBatchRequest"/> to retrieve the specified asset packs.
/// Downloads the asset packs if they aren't already available on disk.
///
/// After download, the assets and/or AssetBundles contained in the asset pack are <b>not</b>
/// loaded into memory. To load them use <see cref="PlayAssetPackRequest.GetAssetLocation"/>
/// or <see cref="PlayAssetPackRequest.LoadAssetBundleAsync"/> on the values of the
/// <see cref="PlayAssetPackBatchRequest.Requests"/> dictionary.
/// </summary>
/// <param name="assetPackNames">A list of requested asset packs.</param>
/// <param name="updateIfAvailable">
/// If true and any of the specified packs are already installed,
/// this method will check for newer versions of them and download them if available.
/// </param>
/// <returns>A request object used to monitor the asynchronous asset pack batch retrieval.</returns>
/// <exception cref="ArgumentException">Throws if assetPackNames contains duplicate entries.</exception>
public static PlayAssetPackBatchRequest RetrieveAssetPackBatchAsync(IList<string> assetPackNames,
bool updateIfAvailable)
{
return Instance.RetrieveAssetPackBatchAsyncInternal(assetPackNames, updateIfAvailable);
}
/// <summary>
/// Starts a PlayAsyncOperation to determine the download size in bytes of the specified asset pack.
/// If the specified asset pack's delivery mode is install-time, then the download size will always be 0.
/// </summary>
public static PlayAsyncOperation<long, AssetDeliveryErrorCode> GetDownloadSize(string assetPackName)
{
return Instance.GetDownloadSizeInternal(assetPackName);
}
/// <summary>
/// Starts a PlayAsyncOperation to gather download information about the specified asset packs.
/// This includes download size and information about asset pack updates.
/// </summary>
/// <param name="assetPackNames">A list of asset packs.</param>
/// <returns>
/// A PlayAsyncOperation with a Dictionary result keyed by asset pack name,
/// containing download info about the specified packs.
/// </returns>
public static PlayAsyncOperation<IDictionary<string, PlayAssetPackDownloadInfo>, AssetDeliveryErrorCode>
GetDownloadInfo(IList<string> assetPackNames)
{
return Instance.GetDownloadInfoInternal(assetPackNames);
}
/// <summary>
/// Starts a PlayAsyncOperation to delete the specified asset pack from internal storage.
/// If the specified asset pack is currently being retrieved, this method will not cancel the
/// retrieval. If the specified asset pack contains any AssetBundles that are already loaded into
/// memory, the AssetBundles will <b>not</b> be unloaded.
/// </summary>
/// <returns>
/// An async operation object used to monitor the asset pack removal. If the files are deleted
/// successfully or if the files don't exist, the returned operation will complete successfully.
/// Otherwise, the operation will complete with an error code.
/// </returns>
public static PlayAsyncOperation<VoidResult, AssetDeliveryErrorCode> RemoveAssetPack(string assetPackName)
{
return Instance.RemoveAssetPackInternal(assetPackName);
}
/// <summary>
/// Shows a confirmation dialog for all currently downloading asset packs that are
/// <see cref="AssetDeliveryStatus.WaitingForWifi"/>.
/// If the user accepts the dialog, then those asset packs are downloaded over cellular data.
///
/// A <see cref="PlayAssetBundleRequest"/> is set to <see cref="AssetDeliveryStatus.WaitingForWifi"/> if
/// the user is currently not on a Wi-Fi connection and the AssetBundle is large or the user has set
/// their download preference in the Play Store to only download apps over Wi-Fi. By showing this
/// dialog, the app can ask the user if they accept downloading the asset packs over cellular data
/// instead of waiting for Wi-Fi.
/// </summary>
/// <returns>
/// A <see cref="PlayAsyncOperation{ConfirmationDialogResult, AssetDeliveryErrorCode}"/> that completes
/// once the dialog has been accepted, denied, or closed.
/// </returns>
public static PlayAsyncOperation<ConfirmationDialogResult, AssetDeliveryErrorCode>
ShowCellularDataConfirmation()
{
return Instance.ShowCellularDataConfirmationInternal();
}
/// <summary>
/// Shows a dialog that asks the user for consent to download packs that are currently in
/// either the <see cref="AssetDeliveryStatus.RequiresUserConfirmation"/> state or the
/// <see cref="AssetDeliveryStatus.WaitingForWifi"/> state.
///
/// A <see cref="PlayAssetBundleRequest"/> is set to
/// <see cref="AssetDeliveryStatus.RequiresUserConfirmation"/> If the download is not able
/// to proceed without user consent. By showing this dialog, the app can ask the user if
/// they accept downloading the asset packs through Google Play. If the app has not been
/// installed by Play, an update may be triggered to ensure that a valid version is
/// installed. This will cause the app to restart and all asset requests to be cancelled.
/// These assets should be requested again after the app restarts.
///
/// A <see cref="PlayAssetBundleRequest"/> is set to
/// <see cref="AssetDeliveryStatus.WaitingForWifi"/> if the user is currently not on a Wi-Fi
/// connection and the AssetBundle is large or the user has set their download preference in
/// the Play Store to only download apps over Wi-Fi. By showing this dialog, the app can ask
/// the user if they accept downloading the asset packs over cellular data instead of
/// waiting for Wi-Fi.
/// </summary>
/// <returns>
/// A <see cref="PlayAsyncOperation{ConfirmationDialogResult, AssetDeliveryErrorCode}"/>
/// that completes once the dialog has been accepted, denied, or closed.
/// </returns>
public static PlayAsyncOperation<ConfirmationDialogResult, AssetDeliveryErrorCode>
ShowConfirmationDialog()
{
return Instance.ShowConfirmationDialogInternal();
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 7e93d382fc6b64f72b7e5099c10836cf
timeCreated: 1548718888
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,62 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Google.Play.AssetDelivery
{
/// <summary>
/// A <a href="https://docs.unity3d.com/ScriptReference/CustomYieldInstruction.html">CustomYieldInstruction</a>
/// used to monitor the asynchronous retrieval of a batch of asset packs.
/// </summary>
public abstract class PlayAssetPackBatchRequest : CustomYieldInstruction
{
/// <summary>
/// A dictionary of asset pack requests, keyed by name, that are present in this batch.
/// </summary>
public IDictionary<string, PlayAssetPackRequest> Requests;
/// <summary>
/// Returns true if all requests in this batch are in either the <see cref="AssetDeliveryStatus.Available"/> or
/// <see cref="AssetDeliveryStatus.Failed"/> status, false otherwise.
/// </summary>
public bool IsDone { get; protected set; }
/// <summary>
/// Event indicating that all the requests in this batch are complete. If an event handler is registered after
/// the operation has completed, and thus after this event has been invoked, then the handler will be called
/// synchronously.
/// </summary>
public virtual event Action<PlayAssetPackBatchRequest> Completed = delegate { };
/// <summary>
/// Implements the <a href="https://docs.unity3d.com/ScriptReference/CustomYieldInstruction-keepWaiting.html">CustomYieldInstruction.keepWaiting</a>
/// property so that this request can be yielded on in a coroutine.
/// </summary>
public override bool keepWaiting
{
get { return !IsDone; }
}
/// <summary>
/// Invokes the <see cref="Completed"/> event.
/// </summary>
protected void InvokeCompletedEvent()
{
Completed.Invoke(this);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f40dc8f7ed954772bc3e54feaad0e837
timeCreated: 1588791101

View File

@@ -0,0 +1,59 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace Google.Play.AssetDelivery
{
/// <summary>
/// Download information about a particular asset pack.
/// </summary>
public abstract class PlayAssetPackDownloadInfo
{
/// <summary>
/// The asset pack's download size in bytes.
/// If the asset pack's delivery mode is install-time, then the download size will always be 0.
/// </summary>
public long DownloadSize { get; protected set; }
/// <summary>
/// An enum describing whether or not a newer version of the asset pack is available for download.
/// </summary>
public AssetPackUpdateAvailability UpdateAvailability { get; protected set; }
/// <summary>
/// The version tag of the latest available version of the asset pack. This field might match
/// <see cref="InstalledVersionTag"/>, in which case no update is available.
///
/// <para>
/// The tag is set by the developer at upload-time and can be used to identify an asset pack version.
/// </para>
///
/// <para>Empty string if the asset pack does not exist or no information is available.</para>
/// </summary>
public string AvailableVersionTag { get; protected set; }
/// <summary>
/// Returns the version tag of the currently installed asset pack. If no version tag was set for this
/// pack version then the app version code will be returned instead.
///
/// <para>
/// The tag is set by the developer at upload-time and can be used to identify an asset pack version.
/// </para>
///
/// <para>
/// Empty string if no version of this pack is currently installed.
/// </para>
/// </summary>
public string InstalledVersionTag { get; protected set; }
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 6b5b3ff2c7b244e4836a9fcbe42448e2
timeCreated: 1621901087

View File

@@ -0,0 +1,103 @@
// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using UnityEngine;
namespace Google.Play.AssetDelivery
{
/// <summary>
/// A <a href="https://docs.unity3d.com/ScriptReference/CustomYieldInstruction.html">CustomYieldInstruction</a>
/// used to monitor the asynchronous retrieval of an asset pack.
/// </summary>
public abstract class PlayAssetPackRequest : CustomYieldInstruction
{
/// <summary>
/// Progress between 0 and 1 indicating the overall download progress of this request.
/// Note: If this value is equal to 1, it does not mean that the request has completed,
/// only that the Downloading stage is finished.
/// </summary>
public float DownloadProgress { get; protected set; }
/// <summary>
/// The error that prevented this requested from completing successfully.
/// In the case of a successful request, this will always be <see cref="AssetDeliveryErrorCode.NoError"/>.
/// </summary>
public AssetDeliveryErrorCode Error { get; protected set; }
/// <summary>
/// Returns true if this request is in the <see cref="AssetDeliveryStatus.Available"/> or
/// <see cref="AssetDeliveryStatus.Failed"/> status, false otherwise.
/// </summary>
public bool IsDone { get; protected set; }
/// <summary>
/// An enum indicating the status of this request (downloading, downloaded, installed etc.)
/// If the request completed successfully, this value should be <see cref="AssetDeliveryStatus.Available"/>.
/// If an error occured, it should be <see cref="AssetDeliveryStatus.Failed"/>.
/// </summary>
public AssetDeliveryStatus Status { get; protected set; }
/// <summary>
/// Event indicating that the request is completed. If an event handler is registered after the operation has
/// completed, and thus after this event has been invoked, then the handler will be called synchronously.
/// </summary>
public virtual event Action<PlayAssetPackRequest> Completed = delegate { };
/// <summary>
/// Implements the <a href="https://docs.unity3d.com/ScriptReference/CustomYieldInstruction-keepWaiting.html">CustomYieldInstruction.keepWaiting</a>
/// property so that this request can be yielded on in a coroutine.
/// </summary>
public override bool keepWaiting
{
get { return !IsDone; }
}
/// <summary>
/// Retrieves the location of an asset at the specified path within this asset pack.
/// </summary>
/// <param name="assetPath">The path within this asset pack pointing to the desired asset.</param>
/// <returns>
/// An <see cref="AssetLocation"/> object describing the path, offset and size of a the requested asset file
/// within the asset pack.
/// </returns>
public abstract AssetLocation GetAssetLocation(string assetPath);
/// <summary>
/// Loads the AssetBundle located at the specified path within this asset pack.
/// </summary>
/// <param name="assetBundlePath">The path within this asset pack pointing to the desired AssetBundle.</param>
/// <returns>
/// An <a href="https://docs.unity3d.com/ScriptReference/AssetBundleCreateRequest.html">
/// AssetBundleCreateRequest</a> that can be yielded on until the AssetBundle is loaded.
/// </returns>
public abstract AssetBundleCreateRequest LoadAssetBundleAsync(string assetBundlePath);
/// <summary>
/// Cancels the request if possible, setting Status to <see cref="AssetDeliveryStatus.Failed"/> and
/// Error to <see cref="AssetDeliveryErrorCode.Canceled"/>.
/// If the request is already <see cref="AssetDeliveryStatus.Available"/>
/// or <see cref="AssetDeliveryStatus.Failed"/>, then the request is left unchanged.
/// </summary>
public abstract void AttemptCancel();
/// <summary>
/// Invokes the <see cref="Completed"/> event.
/// </summary>
protected void InvokeCompletedEvent()
{
Completed.Invoke(this);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ff97ef6fdbb2491fb530d8567185e132
timeCreated: 1587769068

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: f486a9efd17434cf49a47593f848801d
folderAsset: yes
timeCreated: 1540844190
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,14 @@
{
"name": "com.google.play.assetdelivery",
"displayName": "Google Play Asset Delivery",
"description": "Play Asset Delivery enables AssetBundles and other assets to be packaged into an Android App Bundle and delivered through Google Play.",
"version": "1.9.1",
"unity": "2018.4",
"author": {
"name": "Google LLC"
},
"dependencies": {
"com.google.play.common": "1.9.1",
"com.google.play.core": "1.8.4"
}
}

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5b8c9188eee9641948db3648e00acb10
timeCreated: 1576695771
licenseType: Pro
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant: