2

How can I load an Android asset pack on-demand using Java from the Google Play app bundle?
I have tried passing the parameter and hard coding it in AssetPackManager. I think my problem is associated with not understanding interface.

Some Links

https://developer.android.com/guide/playcore/asset-delivery/integrate-java
The Play Core Java API provides the AssetPackManager class for requesting asset packs, managing downloads, and accessing the assets. You implement this API according to the delivery type of the asset pack you wish to access.

https://developer.android.com/reference/com/google/android/play/core/assetpacks/AssetPackManager#getpacklocation

My asset pack (SongsNW) structure is at the same level indent as app

    app  // my app
        src
           main
                java
                AndroidManifest.xml
            build.gradle

My app level build.gradle (above) lists my AssetPacks

    android {
        other {
            ...
        }
        dynamicFeatures = [':....X', ':SongsNW', ':.....Y', ':.....Z']
    }
    dependencies {
        ....
    }

My Asset Pack (SongsNW)

    SongsNW 
        src
            main
                assets
                    NW folder with assets
                AndroidManifest.xml
            build.gradle
    

My AndroidManifest.xml (under SongsNW above)

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:dist="http://schemas.android.com/apk/distribution"
        package="com.companyname.songsnw">
    
        <dist:module
            dist:instant="false"
            dist:title="@string/title_songsnw">
            <dist:delivery>
                <dist:on-demand/>
            </dist:delivery>
            <dist:fusing dist:include="false" />
        </dist:module>
    </manifest>

My build.gradle (under SongsNW above)

    apply plugin: 'com.android.asset-pack'
    
    assetPack {
        packName = "SongsNW" // Directory name for the asset pack
        dynamicDelivery {
            deliveryType = "on-demand"
        }
    }

LoadAssetPack.java (module)

    package com.companyname.appname;
    
    import android.util.Log;
    import com.google.android.play.core.assetpacks.AssetPackLocation;
    import com.google.android.play.core.assetpacks.AssetPackState;
    import com.google.android.play.core.assetpacks.AssetPackStates;
    import com.google.android.play.core.tasks.OnCompleteListener;
    import com.google.android.play.core.tasks.RuntimeExecutionException;
    import com.google.android.play.core.tasks.Task;
    
    import static android.content.ContentValues.TAG;
    
    
    interface AssetPackManager {
        // I am passing the assetPackName to here with this call:
        // AssetPackLocation assetPackLocation = AssetPackManager.getPackLocation("SongsNW");
        public static final String TAG = "LoadAssetPack";
        public static final String assetPackName = "";
        // public static final String assetPackName = "SongsNW";
        public static final AssetPackLocation assetPacklocation = null;

        public static final AssetPackLocation assetPackLocation = getPackLocation(assetPackName);

        public static AssetPackLocation getPackLocation(String assetPackName) {
            Log.d(TAG, "in AssetPackManager assetPackName:" + assetPackName);
                    AssetPackLocation assetPackLocation = getPackLocation(assetPackName);
            Log.d(TAG, "assetPackName:" + assetPackName + " assetPackLocation: " + assetPackLocation );
            return assetPackLocation;  // null if it isn't complete

        }

        // I need to run the following list, but first I need to understand what I am doing wrong.
        AssetPackStates cancel (List<String> packNames)
        Task<AssetPackStates> fetch (List<String> packNames)
        Task<AssetPackStates> getPackStates (List<String> packNames)
        void registerListener (AssetPackStateUpdateListener listener)
        Task<Void> removePack (String packName)
        Task<Integer> showCellularDataConfirmation (Activity activity)
        void unregisterListener (AssetPackStateUpdateListener listener)
    }

This is not the answer to the above question but I believe it defines the questions better.

First be able to see the original error message.
Increase Android Studio Logcat buffer size to hold 16384 KB (Default 1024 KB)
File > Settings > Editor > General > Console > override console cycle buffer size.
then you can see the error at the top.

message in Logcat:
I/SystemServer: InitBeforeStartServices
W/YouTube: Fetching the Gservices key 'disable_binder_callback_flush' before the end of the bulk initialization
W/Primes: Primes not initialized, returning default (no-op) Primes instance which will ignore all calls.
Please call Primes.initialize(...) before using any Primes API.

Google the above error provides:
Play Services tries to authenticate, closes the profile popup prematurely, fails #2362
https://github.com/playgameservices/play-games-plugin-for-unity/issues/2362

In the following comment they are discussing Google Play services.
... The Web Client ID was the right way to go. Once I got that properly configured it did the trick. The part that wasn't intuitive was the redirect_uri. For anyone running into the same problem because the Google API Console isn't super intuitive: In the credentials section, under the Oauth consent screen tab, toward the bottom is an "Authorized domains" section. In order to add an Authorized domain, you need to type it into the box right below that says example.com.

That brought up a lot of additional questions:
What is the Web Client ID? Where is this credentials section? What is a redirect_uri? What is my Authorized domain? The real question is, Why am I trying to create and manage Google Cloud projects? The answer, I believe, is because that is where Google Play is storing my app bundle.

The answer to properly managing projects probably is in:
https://cloud.google.com/resource-manager/docs/creating-managing-projects

I have found OAuth clients at
Google Play Console > Settings > Developer account > API access

So, my question at this time is: "What is the minimum I need to fill out in Google Play to Initialize the System Server. (Which is my first error statement).

gerardg
  • 203
  • 2
  • 9
  • Pretty comprehensive description here: https://medium.com/mindful-engineering/google-play-asset-delivery-in-android-dcc2059e5a63 – ZP007 Feb 28 '22 at 04:45
  • ZP007 provides a valid link. I did not use it because I had already implemented my solution (see below). – gerardg Mar 02 '22 at 22:25

1 Answers1

0

Google Play said I couldn't store assets in Internal storage > Android > obb anymore so I attempted to implement Asset Packs, failed, and wrote this question. I ended up simply installing each asset on Play Store as an app, and added the following to my help page.

There are NO songs in this app. ZERO. You have to load them from another app. There are currently four other apps that are associated with this app: Birding Via Mic New World, ... Old World, ... Orient Australasia, and ... North American Common.

These apps contain songs for their respective region (called YourRegion below) but no functionality other than supply this app with the songs they contain. You will need to install one (or more if desired) of these and transfer the songs to this app.

If you are running on Android Version 6.0 or greater, verify your permissions are turned on: Settings > Applications > Application Manager > Birding Via Mic > Permissions

To transfer the songs:

  1. Install this Birding Via Mic app.
  2. Install Birding Via Mic_YourRegion app.
  3. Open Birding Via Mic_YourRegion, tap Songs and verify a list of songs is displayed.
  4. In this Birding Via Mic app tap the Path button.
  5. On the Path screen select Birding Via Mic -- YourRegion.
  6. Tap the "Load Now" button. Uninstall the Birding Via Mic_YourRegion app to recover memory.
gerardg
  • 203
  • 2
  • 9