Unable to load LibGdx sound files

I would like to download files directly from the OBB extension file using AssetManager. I implemented my own FileHandleResolver

 public class CustomFileHandleResolver implements FileHandleResolver { @Override public FileHandle resolve(String fileName) { return new CustomFileHandle(fileName); } } 

I installed it in my AssetManager. I created my own FileHandle and I override the 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 downloads all files, such as .PNG, .PACK, .FNT, except for .OGG files, so I think that all sound files will not be downloaded. I get 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 cannot be compressed. In 7zip, I chose compression for the "Store" so that it doesn't compress at all, but still this problem arises.

I went through what happens when files are loaded, and I found that AssetManager calls my CustomFileHandleResolver , which creates a CustomFileHandle . For each file that is not .OGG, it calls InputStream read() . In this function, it loads a file from a zip code, and that’s fine. But, as I said, when it comes to downloading .OGG, this does not call this function. Therefore, he does not even try to get the file from the zip code. The question is why the .OGG file does not call InputStream read() in CustomFileHandle() ?

UPDATE

I went through more and I found out that he will not call InputStream read() , because he somehow cannot create sound from FileHandle. The hint for this is

 CustomFileHandle cannot be cast to AndroidFileHandle 

For now, to create sound, you need to transfer the Handle file.

 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 this soundLoader uses my CustomFileHandleResolver. I do not know if sounds are processed differently than 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 not get into Gdx.files.internal to see if there is any special processing for Sounds.

UPDATE

Further analysis makes me realize that the main problem is what was mentioned earlier.

 CustomFileHandle cannot be cast to AndroidFileHandle 

I do not know why it changes FileHandle to AndroidFileHandle when loading an OGG file. If it downloads files of another different type, this probably means that they are not casting for them. This means that OGG is special and needs casting. Any clues?

+4
java android libgdx apk-expansion-files
source share
3 answers

I did not find a way to download sound files from a zip file. The problem is that AssetManager downloads sound files differently than other file types. The problem was that it drops the FileHandle to AndroidFileHandle , and since CustomFileHandle extends FileHandle cannot pass it to AndroidFileHandle . I could not find a way around this because it was deeply rooted.

 CustomFileHandle cannot be cast to AndroidFileHandle 

In this situation, I had to remove all the sound files from the OBB file and place them with the application. I created another instance of AssetManager just for loading sounds. Thus, sounds load normally, just like when using AssetManager , and for any other type of file I used AssetManager , which uses my own FileHandlerResolver , which uses my own FileHandle class, which returns a file from zip. The only problem with this approach is that you are limited to having audio files of only up to 50 MB.

0
source share

I solved this problem by extracting the zip to a specific folder, and then reading from this external folder.

Extracting zip is done in the following ways:

  public void extract(){ String packageName = getPackageName(); File root = Environment.getExternalStorageDirectory(); File expPath = new File(root.toString() + "/Android/obb/" + packageName); if (expPath.exists()) { String strMainPath = null; try { strMainPath = expPath + File.separator + "main." + getPackageManager().getPackageInfo( getPackageName(), 0).versionCode + "." + packageName + ".obb"; Log.e("Extract File path", "===>"+strMainPath); File f=new File(strMainPath); if(f.exists()){ Log.e("Extract From File path", "===> not exist"); } else { Log.e("Extract From File path", "===> exist"); } String pathToExtract = Environment.getExternalStorageDirectory()+"/"+Cons.FOLDERNAME; Log.e("Extract to path", "===>"+pathToExtract); flag = extractZip(strMainPath,pathToExtract); Log.e("After Extract Zip", "===>"+flag); } catch (NameNotFoundException e) { e.printStackTrace(); } } } private boolean extractZip(String pathOfZip,String pathToExtract) { int BUFFER_SIZE = 1024; int size; byte[] buffer = new byte[BUFFER_SIZE]; try { File f = new File(pathToExtract); if(!f.isDirectory()) { f.mkdirs(); } ZipInputStream zin = new ZipInputStream(new BufferedInputStream(new FileInputStream(pathOfZip), BUFFER_SIZE)); fileNum=0; try { ZipEntry ze = null; while ((ze = zin.getNextEntry()) != null) { String path = pathToExtract +"/"+ ze.getName(); if (ze.isDirectory()) { File unzipFile = new File(path); if(!unzipFile.isDirectory()) { unzipFile.mkdirs(); } } else { updateFileNum(); FileOutputStream out = new FileOutputStream(path, false); BufferedOutputStream fout = new BufferedOutputStream(out, BUFFER_SIZE); try { while ( (size = zin.read(buffer, 0, BUFFER_SIZE)) != -1 ) { fout.write(buffer, 0, size); } zin.closeEntry(); }catch (Exception e) { Log.e("Exception", "Unzip exception 1:" + e.toString()); } finally { fout.flush(); fout.close(); } } } }catch (Exception e) { Log.e("Exception", "Unzip exception2 :" + e.toString()); } finally { zin.close(); } return true; } catch (Exception e) { Log.e("Exception", "Unzip exception :" + e.toString()); } return false; } 

Note. Extract it to a folder. Android, other users will have direct access to assets. For example, they will see images in the Gallery application.

0
source share

Ok, I'm doing it now. Whenever you need to get a real FileHandle in order for the sound loading mechanism to work (or AndroidFileHandle in any other way), unzip this file to a local directory and reuse it if necessary:

  public static FileHandle getRealFileHandle(String zipEntryPath, ZipFile zipFile) { if (Gdx.files.local(zipEntryPath).exists()) { return Gdx.files.local(zipEntryPath); } else { Gdx.app.log(TAG, "Unzipping file '" + zipEntryPath + "'..."); try { FileHandle unzippedFile; ZipEntry entry = zipFile.getEntry(zipEntryPath); if (entry != null) { unzippedFile = Gdx.files.local(zipEntryPath); InputStream is = zipFile.getInputStream(entry); byte[] buffer = new byte[65536]; int readLength; while ((readLength = is.read(buffer)) >= 0) { unzippedFile.writeBytes(buffer, 0, readLength, true); } return unzippedFile; } else { Gdx.app.error(TAG, "Entry '" + zipEntryPath + "' not found inside zip file."); } } catch (IOException ioe) { Gdx.app.error(TAG, "A problem occurred while writing to the local file."); } } return null; } 
0
source share

All Articles