Android assets的一个bug
摘要
Android assets目录下资源文件超过1MB的问题。
Android assets目录下资源文件超过1MB的问题。
由于要显示一些奇奇怪怪的日文字符,我们在应用里放了一个字库文件,譬如叫做jp.ttf
,放在assets
目录下打包。
开发、调试一切正常。可是突然发现,在Android 2.2的设备上,文字无法显示。折腾一番后发现了一些故事,也产生了更多疑问。
-
放在
assets
目录下的资源文件不会被映射到R.java
,访问需要AssetManager
类。不同于res/raw
,res/raw
中的资源文件会被映射到R.java
,访问时使用资源ID。 -
能搜索到很多网页(但内容几乎相同)指出
AssetManager
有个bug,不能处理单个超过1MB的文件。但没有说明Android版本。从我们对这个字库的使用来看,Android 2.3以上没有问题。 -
找到Android Issue 39041提到
AssetManager
的一个问题,回复中5楼bite…@gmail.com说,There is a bug in apk de/compression that does not allow using compressed assets which unpack into files larger than 1 mb. This problem is fixed in Android 2.3.
不知道他是不是Project Member,在7楼,他又说,
Android smaller than 2.3 DOES NOT GUARANTEE that loading will succeed. This happens more frequently when there are a lot of similar bytes in a row in the asset file, but not necessary. To be sure you have to split the resource file into small files, that’s it.
而Project Member kr…@android.com说,
Also, do not read files a single byte at a time. Use a large byte buffer.
不知道这里“a large byte buffer”要求达到多少。我们的字库文件
jp.ttf
是超过1MB了,确实也只在Android 2.2上遇到问题。而我们的应用又必须支持Android 2.2。 -
又折腾一番后我们发现,把这个
jp.ttf
改名为jp.xmf
,在Android 2.2上就可以正常访问了。 -
无论文件后缀名是啥,访问方法是一样的,
InputStream in = getResources().getAssets().open("jp.xmf");
第3点里提到的“a large byte buffer”建议得到了验证,应用里由于某种原因需要把这个文件读到一个buffer里再写到另一个路径,这个buffer是1KB,如果调整成1MB,
jp.ttf
就也可以正常访问了。最初,是这样访问的,tf = Typeface.createFromAsset(getAssets(), "jp.xmf");
还是不清楚为什么
jp.xmf
可以工作,jp.ttf
不行?
更新,12月23日。知道了为什么jp.xmf
可以工作,jp.ttf
不行。这个问题可能是试图访问在打包apk时被压缩的资源文件而产生的,因此解决方法确实是改文件后缀名,改成不会在打包apk时被压缩的后缀名。譬如mp3、jpg,或者我们曾经尝试过的xmf。感谢这个提问里CommonsWare的回答。
同时,我们也发现之前“5”中的结论是错误的,对于jp.ttf
,在Android 2.2上增大buffer没有解决问题。可能当时验证的小伙伴一时糊涂用错了手机。关于1MB的问题,还可以参考这个提问。