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

Estoy progtwigndo una caja de resonancia de Android. el problema es que algunos sonidos funcionan, y algunos no funcionan. aquí está el rastreo que recibo de los sonidos que no funciona

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) 

¿algunas ideas?

Existe una limitación 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.

Al tratar con la compresión de activos en las aplicaciones de Android se analizan algunas técnicas para lidiar con archivos comprimidos. Puedes hacer un truco para no comprimir el archivo usando una extensión que no esté comprimida (por ejemplo, mp3 ) o puedes agregarlos manualmente a la aplicación sin compresión en lugar de aapt para hacer el trabajo.

Puede deshabilitar la compresión de activos para ciertas extensiones como estas:

 android { aaptOptions { noCompress "pdf" } } 

Fuente

Esta situación decididamente irritante se produce porque cuando se construye .apk , algunos activos se comprimen antes de almacenarlos, mientras que otros se tratan como si ya estuvieran comprimidos (por ejemplo, imágenes, video) y se dejan en paz. 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 comstackció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 con la que AssetFileDescriptor usa el hecho de que si bien no puedes abrir un AssetFileDescriptor para el activo, aún puedes abrir un InputStream . Puede usar esto para copiar el activo en el caché de archivos de la aplicación y luego devolver un descriptor para eso:

 @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 dejará archivos de caché, pero está bien. Tampoco intenta volver a utilizar los archivos de caché existentes, que pueden o no preocuparse.

Debería obtener esta excepción solo si intenta abrir FileDesriptor . Solo por leer el archivo puede seguir el camino por 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 descomprimido) para llamar a su método getLength() , de lo contrario, debe leer toda la secuencia para determinar su tamaño.

He hecho una caminata, 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(); } } } } } 

Esta excepción puede ser lanzada llamando

 final AssetFileDescriptor afd = activity.getAssets().openFd(path); 

Solucioné el problema guardando el archivo en el directorio res / raw en lugar de la carpeta assets, luego obtengo el AssetFileDescriptor de esta manera:

 final AssetFileDescriptor afd = activity.getResources().openRawResourceFd(rawId); 

Luego, FileNotFoundException se ha ido y el archivo ya no está comprimido.