176 lines
6.1 KiB
C#
176 lines
6.1 KiB
C#
// 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);
|
|
}
|
|
}
|
|
} |