How to access "Extra Android Assets" within Android app?


#1

I have a folder of audio files that I am including in my app via the “Extra Android Assets” Projucer Option.

How do you actually get these assets in the app? I’m fairly new to Android & didn’t see any other documentation about this.


#2

Solved with this (run once upon app initialization):

// Copies the .wav files in /assets into the app data directory upon first launch.
// Subsequent launches will only copy over new assets, if there are any.
#if JUCE_ANDROID
    // Directory to store /assets files
    const auto dataDirectory = File::getSpecialLocation (File::userApplicationDataDirectory).getChildFile ("data");    
    if (! dataDirectory.exists()) {
        dataDirectory.createDirectory();
    }
    // See if there are any files installed from previous launches of the app
    Array<File> installedData = dataDirectory.findChildFiles (File::findFiles, true, "*");
    StringArray installedDataFilenames;
    for (auto data : installedData) {
        installedDataFilenames.add (data.getFileName());
    }
    // Extract entries from the APK file under the assets/ folder (generated by ProJucer)
    ZipFile zip (File::getSpecialLocation (File::currentApplicationFile));
    for (int i = 0; i < zip.getNumEntries(); i++) {
        if (auto* entry = zip.getEntry (i)) {
            // Only worried about .wav files for now - don't want to copy the entire APK
            if (entry->filename.endsWithIgnoreCase (".wav")) {
                // Will only copy resource over once
                if (! installedDataFilenames.contains (entry->filename.fromFirstOccurrenceOf ("assets/", false, false))) {
                    // File not installed yet, unpack it.
                    zip.uncompressEntry (i, dataDirectory, true);
                }
            }
        }
    }
#endif

I need to be able to treat these assets as traditional “files”, so merely uncompressing them and using the raw data was not an option.


#3

Using the above example, I access the actual files by this:

File assetsDirectory = File::getSpecialLocation (File::userApplicationDataDirectory).getChildFile ("data").getChildFile ("assets");
Array<File> assets = assetsDirectory.findChildFiles (File::findFiles, false, "*");

#4

Have you looked at how we do this in the DemoRunner on Android? Take a look at the createAssetInputStream() method in JUCE/examples/Assets/DemoUtilities.h.


#5

Yes, but in my case I am using an old C library that has no use for input streams or raw data — it actually needs a traditional File reference (don’t want to touch the old, ugly code if I can avoid it).

So either way I’d need to expand the .zip assets somewhere on the file system.