2011-05-31 11 views
21

estoy programando una caja de resonancia de android. el problema es que algunos sonidos funcionan, y algunos no funcionan. aquí es el rastreo que me sale de los sonidos que no funcionajava.io.FileNotFoundException: este archivo no se puede abrir como un descriptor de archivo; probablemente esté comprimido

05-31 13:23:04.227 18440 18603 W System.err: java.io.FileNotFoundException: This file can not be opened as a file descriptor; it is probably compressed 
05-31 13:23:04.227 18440 18603 W System.err: at android.content.res.AssetManager.openAssetFd(Native Method) 
05-31 13:23:04.227 18440 18603 W System.err: at android.content.res.AssetManager.openFd(AssetManager.java:331) 
05-31 13:23:04.227 18440 18603 W System.err: at com.phonegap.AudioPlayer.startPlaying(AudioPlayer.java:201) 
05-31 13:23:04.227 18440 18603 W System.err: at com.phonegap.AudioHandler.startPlayingAudio(AudioHandler.java:181) 
05-31 13:23:04.235 18440 18603 W System.err: at com.phonegap.AudioHandler.execute(AudioHandler.java:64) 
05-31 13:23:04.235 18440 18603 W System.err: at com.phonegap.api.PluginManager$1.run(PluginManager.java:86) 
05-31 13:23:04.235 18440 18603 W System.err: at java.lang.Thread.run(Thread.java:1096) 

alguna idea?

Respuesta

24

Existen limitaciones para abrir archivos comprimidos en la carpeta de activos. Esto se debe a que los archivos sin comprimir se pueden mapear directamente en la memoria en el espacio de direcciones virtuales de los procesos, evitando así necesitar la misma cantidad de memoria para la descompresión.

Dealing with Asset Compression in Android Apps se describen algunas técnicas para tratar con archivos comprimidos. Puede engañar aapt para que no comprima el archivo utilizando una extensión que no está comprimida (por ejemplo, mp3) o puede agregarlos manualmente al apk sin compresión en lugar de obtener aapt para hacer el trabajo.

+0

gracias, i 'll probar esto ... – nomoral

+0

Por último, una respuesta a todos mis problemas . ¡Esto está muy mal documentado! +1 – Phil

+0

El archivo de activos binarios que tengo es de alrededor de 1.1MB. Cambié el nombre a jpg/png, etc. para que la compresión no se active. Pero cuando se copia a la tarjeta sd, se hincha hasta ~ 8MB. De alguna manera, AssetManager todavía piensa que necesita ser descomprimido. ¿Alguien sabe qué está pasando aquí? – GreenBee

3

Debería obtener esta excepción solo si intenta abrir el FileDesriptor. Solo por leer el archivo puede ir por el InputStream (AssetManager.open("filename.ext")). Esto funcionó para mí.

Si necesita el tamaño del archivo por adelantado, necesita el FileDescriptor (y, por lo tanto, un archivo sin comprimir) para llamar a su método getLength(), de lo contrario, debe leer toda la secuencia para determinar su tamaño.

4

Esta situación decididamente irritante se produce porque cuando se construye el .apk, algunos activos se comprimen antes de almacenarlos, mientras que otros se tratan como ya comprimidos (por ejemplo, imágenes, video) y se dejan solos. El último grupo se puede abrir usando openAssetFd, el primer grupo no puede - si lo intenta, obtiene el error "Este archivo no se puede abrir como un descriptor de archivo, probablemente está comprimido".

Una opción es engañar al sistema de compilación para que no comprima los activos (ver el enlace en la respuesta de @ nicstrong), pero esto es complicado. Es mejor intentar solucionar el problema de una manera más predecible.

La solución que utilizo es que, si bien no puede abrir AssetFileDescriptor para el activo, aún puede abrir InputStream. Usted puede usar esto para copiar el activo en caché de archivos de la aplicación, y luego devolver un descriptor para que:

@Override 
public AssetFileDescriptor openAssetFile(final Uri uri, final String mode) throws FileNotFoundException 
{ 
    final String assetPath = uri.getLastPathSegment(); // or whatever 

    try 
    { 
     final boolean canBeReadDirectlyFromAssets = ... // if your asset going to be compressed? 
     if (canBeReadDirectlyFromAssets) 
     { 
      return getContext().getAssets().openFd(assetPath); 
     } 
     else 
     { 
      final File cacheFile = new File(getContext().getCacheDir(), assetPath); 
      cacheFile.getParentFile().mkdirs(); 
      copyToCacheFile(assetPath, cacheFile); 
      return new AssetFileDescriptor(ParcelFileDescriptor.open(cacheFile, MODE_READ_ONLY), 0, -1); 
     } 
    } 
    catch (FileNotFoundException ex) 
    { 
     throw ex; 
    } 
    catch (IOException ex) 
    { 
     throw new FileNotFoundException(ex.getMessage()); 
    } 
} 

private void copyToCacheFile(final String assetPath, final File cacheFile) throws IOException 
{ 
    final InputStream inputStream = getContext().getAssets().open(assetPath, ACCESS_BUFFER); 
    try 
    { 
     final FileOutputStream fileOutputStream = new FileOutputStream(cacheFile, false); 
     try 
     { 
      //using Guava IO lib to copy the streams, but could also do it manually 
      ByteStreams.copy(inputStream, fileOutputStream); 
     } 
     finally 
     { 
      fileOutputStream.close(); 
     } 
    } 
    finally 
    { 
     inputStream.close(); 
    } 
} 

Esto significa que su aplicación va a dejar los archivos de caché se extiende alrededor, pero eso está bien. Tampoco intenta volver a utilizar los archivos de caché existentes, que pueden o no preocuparse.

1

he hecho un paseo alrededor, yo uso:

ParcelFileDescriptor mFileDescriptor = context.getAssets().openFd(file).getParcelFileDescriptor(); 

Pero ese retorno: java.io.FileNotFoundException: Este archivo no se puede abrir como un descriptor de archivo; es probable que esté comprimido.

En lugar de esta implementación, abro el archivo directamente usando las funciones de ParcelFileDescriptor.

private void openRenderer(Context context,String fileName) throws IOException { 

File file= FileUtils.fileFromAsset(context, fileName); 
     ParcelFileDescriptor parcelFileDescriptor = ParcelFileDescriptor.open(file,ParcelFileDescriptor.MODE_READ_WRITE); 

     mPdfRenderer = new PdfRenderer(parcelFileDescriptor); 
    }` 

    public class FileUtils { 
    private FileUtils() { 
    } 

    public static File fileFromAsset(Context context, String assetName) throws IOException { 
     File outFile = new File(context.getCacheDir(), assetName); 
     copy(context.getAssets().open(assetName), outFile); 

     return outFile; 
    } 

    public static void copy(InputStream inputStream, File output) throws IOException { 
     FileOutputStream outputStream = null; 

     try { 
      outputStream = new FileOutputStream(output); 
      boolean read = false; 
      byte[] bytes = new byte[1024]; 

      int read1; 
      while((read1 = inputStream.read(bytes)) != -1) { 
       outputStream.write(bytes, 0, read1); 
      } 
     } finally { 
      try { 
       if(inputStream != null) { 
        inputStream.close(); 
       } 
      } finally { 
       if(outputStream != null) { 
        outputStream.close(); 
       } 

      } 

     } 

    } 
} 
33

Puede desactivar la compresión de activos para determinadas extensiones de este modo:

android { 
    aaptOptions { 
     noCompress "pdf" 
    } 
} 

Source

+0

en mi caso, ya había un archivo zip en la carpeta de activos. Por lo tanto, comprimió el archivo una vez más durante la compilación. He puesto "zip" en lugar de "pdf" y el error se ha ido. – CodeToLife

+0

Puede verificar qué entradas están comprimidas con este comando: 'unzip -lv MyApplication.apk' 'Almacenado' en la columna 'Método' significa que el archivo no está comprimido. – Shumoapp

Cuestiones relacionadas