无法加载声音文件LibGdx

我想使用AssetManager直接从扩展OBB文件加载文件。 我实现了自己的FileHandleResolver

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

我将它设置为我的AssetManager。 我创建了自己的FileHandle并覆盖了read()函数

 @Override public InputStream read() { InputStream input = null; try { input = GameInfo.expansionFile.getInputStream(file.getPath().replace('\\', '/')); } catch (IOException e) { e.printStackTrace(); } return input; } 

它加载所有文件,如.PNG,.PACK,.FNT,除了.OGG文件,所以我猜所有声音文件都不会被加载。 我收到这个错误:

 com.badlogic.gdx.utils.GdxRuntimeException: com.badlogic.gdx.utils.GdxRuntimeException: Couldn't load dependencies of asset: SFx/button_click.ogg 

而这个错误:

 com.badlogic.gdx.utils.GdxRuntimeException: java.lang.ClassCastException: com.solidgamesstudio.threedefendersn.framework.CustomFileHandle cannot be cast to com.badlogic.gdx.backends.android.AndroidFileHandle 

我读到zip无法压缩。 在7zip中,我选择压缩到“存储”,以便它根本不被压缩,但仍然会出现此问题。

我遍历了加载文件时发生的事情,我发现AssetManager调用了CustomFileHandleResolver ,它创建了CustomFileHandle 。 对于不是.OGG的每个文件,它调用InputStream read() 。 在这个函数中,它从zip加载文件,没关系。 但正如我所说,在加载.OGG时,它不会调用此函数。 所以它甚至没有尝试从zip获取文件。 问题是,为什么.OGG文件不调用CustomFileHandle() InputStream read() CustomFileHandle()

UPDATE

我遍历了更多,我发现它不会调用InputStream read()因为它不能以某种方式从FileHandle创建一个声音。 对此的线索是

 CustomFileHandle cannot be cast to AndroidFileHandle 

在创建声音时,您需要传递fileHandle。

 public Sound newSound (FileHandle fileHandle); 

这是从SoundLoader调用的

 @Override public void loadAsync (AssetManager manager, String fileName, FileHandle file, SoundParameter parameter) { sound = Gdx.audio.newSound(file); } 

而soundLoader使用我的CustomFileHandleResolver。 我不知道Sounds的处理方式是否与其他类型的文件不同。 但默认情况下AssetManager使用

 public class InternalFileHandleResolver implements FileHandleResolver { @Override public FileHandle resolve (String fileName) { return Gdx.files.internal(fileName); } } 

我无法进入Gdx.files.internal以查看是否有任何特殊处理声音。

UPDATE

进一步的分析让我知道主要问题是如前所述。

 CustomFileHandle cannot be cast to AndroidFileHandle 

我不知道为什么它在加载OGG文件时将我的FileHandle转换为AndroidFileHandle。 如果它加载其他类型的文件,这可能意味着它不会为它们进行转换。 这意味着OGG很特别,需要施法。 有什么线索吗?

我还没有找到从zip文件加载声音文件的方法。 问题是AssetManager加载声音文件的方式与其他文件类型不同。 问题是它将FileHandleAndroidFileHandle ,并且由于CustomFileHandle扩展了FileHandle因此无法将其转换为AndroidFileHandle 。 我发现没办法绕过这个,因为它根深蒂固。

 CustomFileHandle cannot be cast to AndroidFileHandle 

在这种情况下,我不得不从OBB文件中取出所有声音文件,并将它们与应用程序放在一起。 我创建了另一个AssetManager实例,仅用于加载声音。 因此,声音正常加载,就像使用AssetManager ,对于任何其他类型的文件,我使用的AssetManager使用我自己的FileHandlerResolver ,它使用我自己的FileHandle类,从zip返回一个文件。 这种方法的唯一问题是您只能使用高达50 MB的声音文件。

我解决了这个问题,将zip解压缩到一个特定的文件夹,然后从该外部文件夹中读取。

拉链的提取是通过以下方法完成的:

  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; } 

注意:将其解压缩到.Android文件夹,其他用户将直接访问资产。 例如,他们将在Gallery应用程序中看到图像。

好吧,我现在正在这样做。 每当你需要获得一个真正的 FileHandle以便声音加载机制起作用时(或者在任何其他情况下, AndroidFileHandle的转换都在困扰你),将该文件解压缩到本地目录并在需要时重用它:

  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; }