Dealing with Asset Compression in Android Apps(避免asset目录下文件被压缩)

转载 2012年03月22日 22:53:54
When developing an Android app, any data file, image or XML file (that is, any Resource or Asset) you use is bundled into your application package (APK) for distribution. The Android Asset Packaging Tool, or aapt, is responsible for creating this bundle, which you can think of as a ZIP file with a particular layout that the Android OS can understand. When your application is installed, whether in development mode or by an end user, this APK file is simply dropped into a special location on the device’s (or emulator’s) filesystem.

As part of preparing your APK, aapt selectively compresses various assets to save space on the device. The way aapt determines which assets need compression is by their file extension. The following code, taken from Package.cpp in the aapt source code, sheds some light on which types of files are not compressed by default:

/* these formats are already compressed, or don't compress well */
static const char* kNoCompressExt[] = {
    ".jpg", ".jpeg", ".png", ".gif",
    ".wav", ".mp2", ".mp3", ".ogg", ".aac",
    ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
    ".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
    ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
    ".amr", ".awb", ".wma", ".wmv"

The only way (that I’ve discovered, as of this writing) to control this behavior is by using the -0 (zero) flag to aapt on the command line. This flag, passed without any accompanying argument, will tell aapt to disable compression for all types of assets. Typically you will not want to use this exact option, because for most assets, compression is a desirable thing. Sometimes, however, you will have a specific type of asset (say, a database), that you do not want to apply compression to. In this case, you have two options.

First, you can give your asset file an extension in the list above. While this does not necessarily make sense, it can be an easy workaround if you don’t want to deal with aapt on the command line. The other option is to pass a specific extension to the -0 flag, such as -0 db, to disable compression for assets with that extension. You can pass the -0 flag multiple times, and each time with a separate extension, if you need more than one type to be uncompressed.

Currently, there is no way to pass these extra flags to aapt when using the ADT within Eclipse, so if you don’t want to sacrifice the ease of use of the GUI tools, you will have to go with the first option, and rename your file’s extension.
So, Why Disable Compression Anyway?

For most types of assets, you shouldn’t need to be concerned with how they are packaged. Given the list of extensions above, Android will do the right thing for a large subset of the files you’ll use. If you have a type of asset that is already compressed by nature of the file type, but doesn’t have one of the sanctioned extensions, you can typically ignore that inconsistency and just allow aapt to try to compress it. It will not be very much, if at all, smaller in the final APK, but the performance hit should be relatively minimal unless you just have tons of these files.

This begs the question, why even bother disabling compression? The not-so-obvious answer is that any compressed asset file with an uncompressed size of over 1 MB cannot be read from the APK. This could come into play if your asset needed to be copied out of the APK and into the app’s writable files area, for example to provide a pre-populated database in your app. When you try to use the various AssetManager or Resources classes’ methods to get an InputStream to the file, it will throw an exception and display a LogCat message like this:

DEBUG/asset(725): Data exceeds UNCOMPRESS_DATA_MAX (1662976 vs 1048576)

The only way around this type of issue is to disable compression for assets that exceed the 1 MB limit. If your file format supports it, you can choose to split the asset into several smaller files that have an uncompressed size of less than 1 MB each, but this can be a real annoyance.

Hopefully the knowledge in this post can help you avoid the headaches I went through to learn it!


要通过new 创建资产资源文件夹
  • nzfxx
  • nzfxx
  • 2016年07月06日 20:41
  • 702


声明:本博客带有[原创]标志的均为原创文章,转载时请注明出处并声明作者felonwan。 参考资料: http://andro...
  • findsafety
  • findsafety
  • 2015年11月25日 15:35
  • 1568


If anyone else is having the same problem, this is how I did it private void copyAssets() { Ass...
  • sky_pjf
  • sky_pjf
  • 2016年09月10日 14:56
  • 1543

Android 拷贝assets目录下所有文件及文件夹到指定路径

  • gan_meng
  • gan_meng
  • 2016年07月25日 12:25
  • 1853


  • qq_33976661
  • qq_33976661
  • 2017年05月25日 20:22
  • 371


Android资源文件分类: Android资源文件大致可以分为两种: 第一种是res目录下存放的可编译的资源文件: 这种资源文件系统会在R.java里面自动生成该资源文件的ID,所...
  • yangyao_iphone
  • yangyao_iphone
  • 2016年03月19日 22:32
  • 1729

关于在Android Studio中使用Assets目录下的资源的问题

一开始在Android Studio中读取Assets目录下的资源的时候,用的是Eclipse下的getResource().getAssets().open("xxx.xml");这里假如是读取一个...
  • shifuhetudi
  • shifuhetudi
  • 2015年04月12日 02:37
  • 46816


有时候发布app,在assets中会自带一些压缩包,打开应用解压放在用户手机sd卡中, 解压这一块就是下面的代码,要判断解压出来的是直接的文件还是一个文件夹,并存储到指定路径下面就好 publ...
  • chenaini119
  • chenaini119
  • 2015年12月25日 15:39
  • 1164


今晚刚好帮一个朋友写了这个小demo,觉得网上可能比较少。因此随便水一篇博客。XD~ 以下以获取图片文件为例,text等其他文件也是同样的获取。 整体流程是Created with Raphaël ...
  • u011435746
  • u011435746
  • 2015年09月12日 21:32
  • 1234

android 解决asset下面文件太大报错问题

Android 中对asset中存放文件 大小有一定限制,如果超过1M会报 Data exceeds UNCOMPRESS_DATA_MAX 这个错误 那么我们怎么解决这个问题呢 首先,我想到的...
  • shaoyezhangliwei
  • shaoyezhangliwei
  • 2016年05月30日 15:30
  • 3284
您举报文章:Dealing with Asset Compression in Android Apps(避免asset目录下文件被压缩)