我想使用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很特别,需要施法。有线索吗?
答案 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;
}