I would like to load files directly from expansion OBB file by using AssetManager. I implemented my own FileHandleResolver
public class CustomFileHandleResolver implements FileHandleResolver
{
@Override
public FileHandle resolve(String fileName) {
return new CustomFileHandle(fileName);
}
}
I set it to my AssetManager. I created my own FileHandle and I override read() function
@Override
public InputStream read()
{
InputStream input = null;
try {
input = GameInfo.expansionFile.getInputStream(file.getPath().replace('\\', '/'));
} catch (IOException e) {
e.printStackTrace();
}
return input;
}
It loads all the files like .PNG, .PACK, .FNT, except .OGG files, so I guess that all sound files won't be loaded. I'm getting this error:
com.badlogic.gdx.utils.GdxRuntimeException: com.badlogic.gdx.utils.GdxRuntimeException: Couldn't load dependencies of asset: SFx/button_click.ogg
And this error:
com.badlogic.gdx.utils.GdxRuntimeException: java.lang.ClassCastException: com.solidgamesstudio.threedefendersn.framework.CustomFileHandle cannot be cast to com.badlogic.gdx.backends.android.AndroidFileHandle
I read that zip can not be compressed. In 7zip I selected compression to "Store" so that it's not compressed at all, but still this problem occurs.
I traversed what is happening when files are being loaded and I found that AssetManager calls my CustomFileHandleResolver
which creates CustomFileHandle
. For every file that is not .OGG it calls InputStream read()
. In this function it loads the file from the zip and it's fine. But as I said when it comes to loading .OGG it doesn't call this function. So it's not even trying yet to get the file from the zip. Question is, why .OGG file doesn't call InputStream read()
in CustomFileHandle()
?
UPDATE
I traversed more and I found out that it won't call InputStream read()
because it can't create a Sound from FileHandle somehow. Clue to this is
CustomFileHandle cannot be cast to AndroidFileHandle
While to create a sound you need to pass fileHandle.
public Sound newSound (FileHandle fileHandle);
This is called from SoundLoader
@Override
public void loadAsync (AssetManager manager, String fileName, FileHandle file, SoundParameter parameter) {
sound = Gdx.audio.newSound(file);
}
And that soundLoader uses my CustomFileHandleResolver. I don't know if Sounds are handled differently then other types of files. But by default AssetManager uses
public class InternalFileHandleResolver implements FileHandleResolver {
@Override
public FileHandle resolve (String fileName) {
return Gdx.files.internal(fileName);
}
}
I can't get into Gdx.files.internal
to see if there are any special handling for Sounds.
UPDATE
Further analysis give me clue that the main problem is this as mentioned before.
CustomFileHandle cannot be cast to AndroidFileHandle
I don't know why it's casting my FileHandle to AndroidFileHandle while loading OGG file. If it loads fine other type of files, that probably means it doesn't do casting for them. That means that OGG is special and it needs casting. Any clues?
I have not found a way to load sound files from the zip file. Problem is that
AssetManager
loads sound files differently than other file types. Problem was that it is castingFileHandle
toAndroidFileHandle
, and sinceCustomFileHandle
extendsFileHandle
it's impossible to cast it toAndroidFileHandle
. I found no way to go around this, because it's deeply rooted.In this situation I had to take out all sound files from the OBB file and put them together with the app. I created another instance of AssetManager just for loading sounds. So, sounds are loaded normally as you would with
AssetManager
and for any other type of file I usedAssetManager
that uses my ownFileHandlerResolver
which uses my ownFileHandle
class that returns a file from the zip. The only problem with this approach is that you are limited to having sounds files only up to 50 MB.I solved this problem extracting the zip to a specific folder, and then reading from that external folder.
The extraction of the zip is done by these methods:
Note: Extract it to .Android folder, otherwhise users will have direct acces to the assets. For example they will see the images in the Gallery app.
Well, I'm doing this currently. Whenever you need to get a real
FileHandle
in order for the sound loading mechanism to work (or in any other case were the casting toAndroidFileHandle
is bothering you), unzip that file to a local directory and reuse it if needed: