无法加载声音文件LibGdx

时间:2014-04-30 13:06:35

标签: java android libgdx apk-expansion-files

我想使用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;
}

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

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中,我选择压缩到" Store"所以它根本没有压缩,但仍然会出现这个问题。

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

更新

我越走越远,我发现它不会调用CustomFileHandle(),因为它无法以某种方式从FileHandle创建声音。对此的线索是

InputStream read()

创建声音时需要传递fileHandle。

CustomFileHandle cannot be cast to AndroidFileHandle

这是从public Sound newSound (FileHandle fileHandle);

调用的
SoundLoader

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

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

我无法进入public class InternalFileHandleResolver implements FileHandleResolver { @Override public FileHandle resolve (String fileName) { return Gdx.files.internal(fileName); } } 以查看是否对声音有任何特殊处理。

更新

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

Gdx.files.internal

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

3 个答案:

答案 0 :(得分:0)

我还没有找到一种从zip文件加载声音文件的方法。问题是AssetManager加载声音文件的方式与其他文件类型不同。问题在于它将FileHandle投射到AndroidFileHandle,并且由于CustomFileHandle延伸FileHandle,因此无法将其投射到AndroidFileHandle。我发现没有办法解决这个问题,因为它根深蒂固。

CustomFileHandle cannot be cast to AndroidFileHandle

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

答案 1 :(得分:0)

我解决了将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文件夹,其他用户将直接访问资产。例如,他们将在图库应用中看到图像。

答案 2 :(得分:0)

好吧,我现在正在这样做。每当你需要获得真实的 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;
}