How to test Addressables for Play Asset Delivery (PAD)?

Hi, how am I supposed to test Addressables using PAD? is there any way to test it or is it a requirement to build it → upload to Play Console → Waiting → Testing. It makes the test and debug phase truly cumbersome, I would be surprised it is actually the case.

Maybe the only way to test it out is by “simulating it” in Unity Editor. So I ended up having 3 button:

  1. Download the asset pack (problem: go to 0 to 1 instantly. Is that normal?)
  2. Uninstall the asset pack
  3. Get the size of the asset pack (problem: return 0)
using System.Collections;
    using UnityEngine;
    using UnityEngine.AddressableAssets;
    using UnityEngine.ResourceManagement.AsyncOperations;
    

    public static class ManagePack
    {

        public enum State
        {
            InProgress,
            Succeeded,
            Failed
        }


        public static IEnumerator Download(AssetLabelReference label, System.Action<float, State> callback)
        {
            var handle = Addressables.DownloadDependenciesAsync(label);

            while (!handle.IsDone)
            {
                callback?.Invoke(handle.PercentComplete, State.InProgress); // Ongoing download
                Debug.Log($"{label.labelString} install in progress.. {handle.PercentComplete}");
                yield return null;
            }

            if (handle.Status == AsyncOperationStatus.Succeeded)
            {
                callback?.Invoke(1f, State.Succeeded); // Success
                Debug.Log($"{label.labelString} installed successfully!");
            }
            else
            {
                callback?.Invoke(0f, State.Failed); // Failure
                Debug.LogError($"Failed to install {label.labelString}: {handle.OperationException.Message}");
            }

            handle.Release();
        }
        

        public static void Uninstall(AssetLabelReference label, System.Action<float, State> callback)
        {
            var handle = Addressables.ClearDependencyCacheAsync(label, true);
            handle.Completed += (AsyncOperationHandle<bool> op) =>
            {
                while (!op.IsDone)
                {
                    callback?.Invoke(op.PercentComplete, State.InProgress);
                    Debug.Log($"{label.labelString} uninstall in progress.. {op.PercentComplete}");
                }

                if (op.Status == AsyncOperationStatus.Succeeded)
                {
                    callback?.Invoke(1f, State.Succeeded);
                    Debug.Log($"{label.labelString} uninstalled successfully!");
                }
                else
                {
                    callback?.Invoke(0f, State.Failed);
                    Debug.Log($"Failed to uninstall {label.labelString}: {op.OperationException.Message}");
                }

                handle.Release();
            };
        }




        public static void GetSize(AssetLabelReference label, System.Action<State> callback)
        {
            var handle = Addressables.GetDownloadSizeAsync(label);
            handle.Completed += (AsyncOperationHandle<long> op) =>
            {
                if (op.Status == AsyncOperationStatus.Succeeded)
                {
                    long size = op.Result; // Size in bytes
                    callback?.Invoke(State.Succeeded);
                    Debug.Log($"{label.labelString ?? "AssetGroup"} size: {size / 1024f / 1024f:F2} MB");
                    Debug.Log($"{label.labelString ?? "AssetGroup"} size: {size:F6} MB");
                }
                else if (op.Status == AsyncOperationStatus.Failed)
                {
                    callback?.Invoke(State.Failed);
                    Debug.LogError($"Failed to get size for {label.labelString ?? "AssetGroup"}: {op.OperationException.Message}");
                }

                handle.Release();
            };
        }
    }

Not sure, but there is Unity Remote, which plugged with USB cable(better alternative than wifi) to enable Unity Editor debugging(and testing) on phone directly from editor…

but there are also best practices from Unity blog or Getting Started with Addressables learnable among others from blog addressables and profiler usage… among other phone and other optimization deliveries or phone Unity solutions or multiplayer phone stack or ads

1 Like

If you Build&Run AAB from the Unity Editor then PAD related behavior on the device would be pretty close to the Google Play. All fast-follow and on-demand would be uploaded to the device, but they would not be immediately available. So basically the only difference is that “downloading” happens almost immediately.

1 Like

Thanks for the insight! I forgot that there’s an internal test feature in Google Play, so I tested it there and downloaded the app. Everything works fine with the code shown above, but there’s an issue with handle.PercentComplete. It doesn’t return progress like “12%” or “46%”—instead, it jumps from 0 to 1 as soon as the download is complete. I can see the asset pack being downloaded in the notifications, but in-game, the progress shows 0 until the download is finished, at which point it jumps to 1.

Also, the uninstall function doesn’t seem to uninstall the pack once installed, as well as the GetSize function that always return 0 :confused:

Do you mean AndroidAssetPackInfo.transferProgress? If yes, then it is actually expected behavior. Our API is just a wrapper around Google’s Java API. This value comes from here. And as you can see percentage makes sense only for TRANSFERRING state, which means that asset pack is already downloaded and it is being decompressed, which happens quite fast, at least comparing to downloading. If you want to see the downloading progress, it’s better to use AndroidAssetPackInfo.bytesDownloaded property.
As for the uninstalling - TBH I’m not sure, but again we are just wrapping Google’s API, so most likely this is the way how it works.

I’m so confused…

I can’t figuring out, it seems there’s a lot of different solutions am I right?

Addressables for Android: Addressables for Android package | Addressables for Android | 1.0.4

PAD API (wrapper of Google’s PlayCore plugin) by Unity: Unity - Scripting API: AndroidAssetPacks (just gives you the methods, but i have absolutely no clue how should i work with them)

What should i use? there is not any example of piece of code, very few documentation here and there that got me almost nowhere as for now… how to work with Addressables and Google Play Asset Delivery (PAD) ? Is there any project code sample or any such thing?

It really depends on what are you going to achieve.
If your project is using Addressables then using Addressables for Android package is the obvious solution. In this case you don’t need to change the code, everything should work out of the box. You just need to add Play Asset Delivery schema to your addressable groups and select delivery types. You don’t need to worry about downloading asset packs yourselves, the package takes care of it. The package includes a very simple sample. Just install it and try to play with it.
If you are not using Addressables, then you can use asset packs directly, but this is more tricky. Basically you can pack anything into custom asset packs. But you should add to your code scripts to download asset packs and to use their content. In case of custom asset packs everything is packed as is, without any processing.
I agree that we should add some sample code to our documentation. You can use this simplified code snippet as a guide:

    string downloadPack;

    void CheckStatus(string packName)
    {
        AndroidAssetPacks.GetAssetPackStateAsync(new[] { packName }, StateQueryResult);
    }

    void DownloadAssetPack(string packName)
    {
        downloadPack = packName;
        StartCoroutine(DownloadAssetPackAsync());
    }

    void RemoveAssetPack(string packName)
    {
        AndroidAssetPacks.RemoveAssetPack(packName);
        CheckStatus(packName);
    }

    void DownloadProgress(AndroidAssetPackInfo info)
    {
        Debug.Log($"Downloading {info.name} {info.size} {info.bytesDownloaded}");
    }

    void StateQueryResult(ulong totalSize, AndroidAssetPackState[] states)
    {
        Debug.Log($"Pack name: {states[0].name} Pack state: {states[0].status} Pack size: {totalSize}";
        // here you can add specific processing for different states 
    }

    IEnumerator DownloadAssetPackAsync()
    {
        var op = AndroidAssetPacks.DownloadAssetPackAsync(new[] { downloadPack }, DownloadProgress);
        while (!op.isDone)
        {
            yield return new WaitForSeconds(0.1f);
        }
        CheckStatus(downloadPack);
        yield return null;
    }

    // reading text file from the asset pack
    // can be called after asset pack is downloaded (its state is AndroidAssetPackStatus.Completed)
    string ReadAssetPack(string packName, string fileName)
    {
        string path = AndroidAssetPacks.GetAssetPackPath(packName);
        return File.ReadAllText(Path.Combine(path, fileName));
    }

Well, this code would be perfect as a sample, this is what I needed, thank you so much!