2014-04-30 5 views
4

AssetManager를 사용하여 확장 OBB 파일에서 직접 파일을로드하고 싶습니다. 내 자신을 구현했습니다사운드 파일을로드 할 수 없습니다. LibGdx

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

내 AssetManager에 설정했습니다. 난 내 자신의 파일 핸들 생성과 나는() 함수 읽어 오버라이드 (override)하는

@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: java.lang.ClassCastException: com.solidgamesstudio.threedefendersn.framework.CustomFileHandle cannot be cast to com.badlogic.gdx.backends.android.AndroidFileHandle 

내가 그 지퍼 압축 할 수 없습니다 읽어

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

그리고이 오류 :이 오류를 받고 있어요. 7zip에서 "Store"로 압축을 선택하여 전혀 압축되지는 않지만 여전히이 문제가 발생합니다.

파일이로드 될 때 무슨 일이 벌어지고 AssetManager가 CustomFileHandleResolver을 호출하여 CustomFileHandle을 생성하는 것을 발견했습니다. .OGG가 아닌 모든 파일에 대해서는 InputStream read()이 호출됩니다. 이 함수에서는 zip 파일을로드합니다. 하지만 .OGG를로드 할 때이 함수를 호출하지 않습니다. 따라서 zip 파일을 아직 가져 오지 못했습니다. 문제는 .OGG 파일이 을 CustomFileHandle()에 호출하지 않는 이유는 무엇입니까?

UPDATE

좀 더를 통과하고 난 어떻게 든부터는 다음에서 사운드를 만들 수 있기 때문에 InputStream read()를 호출하지 않습니다 것을 알아 냈다. 이것에 대한 단서는

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를 사용합니다. 사운드가 다른 유형의 파일과 다르게 처리되는지는 알 수 없습니다. 나는 소리에 대한 특별한 취급이 있는지 Gdx.files.internal로 얻을 수

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

그러나 기본적으로 AssetManager를 사용합니다.

UPDATE

추가 분석은 나에게 전에 언급 한 바와 같이 주요 문제는이 것을 단서를 제공합니다. OGG 파일을로드하는 동안이 AndroidFileHandle 내 파일 핸들 캐스팅 왜

CustomFileHandle cannot be cast to AndroidFileHandle 

나도 몰라. 다른 유형의 파일을로드하는 경우에는 캐스팅하지 않는다는 의미 일 수 있습니다. 즉, OGG는 특별하고 캐스팅이 필요합니다. 모든 단서?

+0

왜 사용자 정의 'FileHandleResolver'를 만드나요? 당신은'assetManager.load ("SFx/button_click.ogg", Sound.class)'및'Sound sound = assetManager.get ("SFx/button_click.ogg", Sound.class)'를 수행하면됩니다. 이것은 libgdx의 모든 표준 기능입니다. – noone

+0

"확장 OGG에서 직접"철자를 잘못 입력했는데 "OBB"여야합니다. 명확히하기 위해, 나는 모든 자산이있는 내 자신의 OBB 확장 파일을 가지고 있습니다. 모든 파일을로드해야합니다. 나는 이것을하기 위해 AssetManager를 사용하고있다. 따라서 zip 파일의 특정 에셋 파일을 가리키는 자체 FileHandler가 필요합니다. 그리고 내 자신의 FileHandler를 사용하는 자체 FileHandleResolver가 필요합니다. – draziw

+0

흥미로운 질문입니다. 자신을 찾을 수 있도록 여기에 해결책을 게시하십시오. – noone

답변

0

zip 파일에서 사운드 파일을로드하는 방법을 찾지 못했습니다. 문제는 AssetManager이 다른 파일 유형과 사운드 파일을 다르게로드한다는 것입니다.문제는 FileHandleAndroidFileHandle 번으로 캐스팅하고 CustomFileHandleFileHandle 개로 확장 했으므로 AndroidFileHandle으로 전송하는 것이 불가능하다는 것입니다. 깊이 뿌리 박았 기 때문에 나는이 문제를 해결할 길을 찾지 못했습니다.

CustomFileHandle cannot be cast to AndroidFileHandle 

이 상황에서 나는 OBB 파일에서 모든 사운드 파일을 꺼내서 앱과 함께 넣어야했습니다. 나는 AssetManager의 또 다른 인스턴스를 사운드를로드하기 위해 만들었습니다. 그래서 소리는 정상적으로 AssetManager과 같이로드되고 다른 형식의 파일은 내 을 사용합니다. 내 FileHandlerResolver은 내 FileHandle 클래스를 사용하여 zip 파일을 반환합니다. 이 방법의 유일한 문제점은 사운드 파일을 최대 50MB까지만 가질 수 있다는 것입니다.

+0

안녕하세요, @ user2974885, 제발 도와주세요. 어떻게 이미지를로드 할 수 있었습니까? 동일한 오류가 발생했습니다. "자산의 종속성을로드 할 수 없습니다." 거래가 무엇입니까? 어떻게 작동 시켰 니? –

+0

안녕하세요. chelo_c. OBB 파일에서 이미지를로드하려고합니까? 그렇지 않다면 AssetManager의 인스턴스를 만든 다음 AssetManager.load() 함수를 사용하여 이미지, 사운드 등을로드하는 작업을 재정의 할 필요가 없습니다. – draziw

+1

확장 파일에서 이미지를로드하려는 경우 이 스레드 : http://stackoverflow.com/questions/23342450/getapkexpansionzipfile-returns-null/23388998#23388998 – draziw

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 폴더에 압축을 풉니 다, otherwhise 사용자는 자산에 직접 액세스를있을 것이다. 예를 들어 갤러리 앱에서 이미지를 볼 수 있습니다.

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