Android - Assets Manager cannot find audio files

Hello Guys,
Assets manager in my Android games is able to find 3d models & textures but for some reason fails to find audio files. Here is the exception I’m getting:

   java.lang.UnsupportedOperationException: Cannot load audio files from classpath.Place your audio files in Android's assets directory
        at com.jme3.audio.plugins.NativeVorbisLoader.load(NativeVorbisLoader.java:122)
        at com.jme3.asset.DesktopAssetManager.loadLocatedAsset(DesktopAssetManager.java:260)
        at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:374)
        at com.jme3.audio.AudioNode.<init>(AudioNode.java:164)
        at com.jme3.audio.AudioNode.<init>(AudioNode.java:144)
        at com.scenemaxeng.projector.SceneMaxApp.loadAudioResource(SceneMaxApp.java:880)
        at com.scenemaxeng.projector.SceneMaxApp.loadResource(SceneMaxApp.java:864)
        at com.scenemaxeng.projector.SceneMaxApp.run(SceneMaxApp.java:719)
        at com.abware.scenemax3dgamehub.JmeProjectorFragment.runScript(JmeProjectorFragment.java:63)
        at com.abware.scenemax3dgamehub.ui.FullscreenGameActivity$7.run(FullscreenGameActivity.java:255)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

I’m using FileLocator with my assets manager to all the needed assets

assetManager.registerLocator

and as I said it works with 3d models & textures but not with audio files…
It’s not an option for me to put my audio files in the assets folder since my games & assets are dynamic (generated).

What can be done?
Thank you.

EDIT: I see that the assets manager’s file locator DID find the audio file but inside the NativeVorbisLoader class in the “load” method it would not accept AssetInfoFile but only AndroidAssetInfo so I wonder if the “load” method was the correct one to call… Looks like the “load” method will only work with assets put inside the assets folder. File assets should be loaded with other load method. I think.

2 Likes

So, you are using DesktopAssetManager to load Android Audio ?

I think you can just make sceneMax3d copy the assets (using File io & streams or even cmd commands) generated by the project in general into the asset folder so you can package apk & send to users in future, i mean by making the assets a part of android apk…but dynamically.

As you can see here, this is the android asset folder, i have my jme assetFolder there, i can make a java program to copy/paste any assets into this folder so android.content.res.AssetManager can locate my resources :

Yeh you are right, i rechecked this back, it’s protected against other Types of AssetInfo

Try using :

by calling :

assetManager.loadAudio(new AudioKey(name:String, bool:Boolean)); explicitly…

If you look at the code, all that method does is call loadAsset(key). Which is the same thing already being called by AudioNode… which OP can’t change anyway.

1 Like

I’m not generating APKs. so copy to assets folder will not help here.
What I don’t understand is why all other assets can be loaded from the internal storage but audio file are not…

1 Like

When jme initializes assetManager through the LegacyApplication, it does getResources for the current class to locate the asset folder using SystemDelegate & it then passes that to the DesktopAssetManager to locate assets, but if the platform is android then that will use Android.cfg file instead of getResources which will direct it to com.jme3.asset.plugins.AndroidLocator instead of using DesktopAssetManager,

So, i am not sure if calling registerLocator would override initAssetManager() call that LegacyApplication does…

ApKs are generated automatically by the android gradle builder, before any installations are done…

Inside NativeVorbisLoader there is a restriction to support only loading from the assets resources:

 @Override
    public Object load(AssetInfo assetInfo) throws IOException {
        AudioKey key = (AudioKey) assetInfo.getKey();
        if (!(assetInfo instanceof AndroidLocator.AndroidAssetInfo)) {
            throw new UnsupportedOperationException("Cannot load audio files from classpath." + 
                                                    "Place your audio files in " +
                                                    "Android's assets directory");
        }
        
        if (key.isStream()) {
            return loadStream(assetInfo);
        } else {
            return loadBuffer(assetInfo);
        }
    }

And I don’t understand why is that limmitation?

2 Likes

Yes I understand that but my Android programs are not APKs…

So, you are trying to load assets from android internal storage ?

yes! and its working perfectly except audio files for some reason. Models, textures anything is loaded perfectly from the storage but not audio files (OGG types). WAV files has another loader which I think doesn’t have this restriction but I got a crash there which I need to check…

1 Like

I didn’t succeed to load OGG files from android assets, but i cannot remember the problem, if wav file works then ogg should too…this restriction to the audioData not to the extension of audio.

But are you using Custom AssetLocator class ?

I think NativeVorbisLoader is dedicated to OGG files so the limitation is for OGG types

2 Likes

I’m using the regular FileLOcator and it’s working just fine

I can think of a solution, but it may be complex & it may not work…

So, create a custom Class of AssetLocater, then inside locate() use activityContext.getExternalFilesDir() it returns File pointing at /shared/0/emulated/ your internal storage dir, to create streams that will point to the asset folder you have inside the internal storage

Then registerLocator(clazzName)

So generally you will substitute the use of AndroidLocator class…

But there is no problem with locating the OGG file. it is located OK but the asset manager’s FileLocator. the problem is with the NativeVorbisLoader which for some reason doesn’t allow loading files which are not from the assets folder

1 Like

I would like to try compiling the NativeVorbisLoader and try removing that restriction

2 Likes

By the way NativeVorbisImageLoader seems to only use OGG :

This file is loaded by the JmeSystemDelegate, triggered by the LegacyApplication if the system fails to use getResources.

The only workaround I can think about is not letting JME playing sounds but to delegate the play sound command to Android itself but I really don’t want to go to that path…

1 Like

Its already there, but using NDK, Android Media from SDK uses Android NDK too…

What I think is that if all other resources are working fine from storage then sound files should work too. there is no reason why it should not work

2 Likes