我的 Android 应用在启动时会从其 assets 目录加载一个数据文件,并且我已经知道解压缩后的大小,所以我需要写的是:
byte[] data = new byte[ /* decompressed size here */ ];
new org.tukaani.xz.XZInputStream(context.getAssets().open("file.xz")).read(data);
然后将git clone https://git.tukaani.org/xz-java.git 和cp -r xz-java/src/org 放入我的应用程序的src 目录(并确保在我的javac 命令行中提及所有.java 文件—我仍然使用老式命令行脚本来编译我的应用程序;我没有为 Android Studio 或 Gradle 设置它们)。
但是,生成的应用需要 6 秒在 2013 年 Sony Xperia Z Ultra(Android 4.4)上解压缩 3M 压缩数据,并更改 @ 的压缩级别987654328@ 对 6 秒的启动没有明显影响。是的,在运行 Android 10 的 2018 年三星 S9 上只需要 1 秒,但需要更多压缩的是较旧的手机,因为 它们是可用空间较少的手机,因此增加了不可接受的启动延迟旧设备上的应用似乎弄巧成拙,尤其是当替代 java.util.zip.Inflater 接近即时时:
byte[] data = new byte[ /* compressed size here */];
context.getAssets().open("file.z").read(data);
java.util.zip.Inflater i=new java.util.zip.Inflater();
i.setInput(data);
byte[] decompressed=new byte[ /* decompressed size here */ ];
i.inflate(decompressed); i.end();
data = decompressed; /* allow earlier byte[] to be gc'd */
对于快速启动,您只需支付 APK 大小比使用 xz 文件的 APK 大小增加 20% 的费用(我使用 zopfli 压缩以获得比 gzip -9 小一点点,尽管它仍然大于xz -0)。
Tukaani 的代码目前似乎无法提供与 setInput 等效的代码。 Tukaani 的 XZDecDemo.java 包含评论“由于 XZInputStream 无论如何都会在内部进行一些缓冲,因此这里似乎不需要 BufferedInputStream 来提高性能”,但为了完整起见,我还是尝试了:
byte[] data = new byte[ /* decompressed size here */ ];
new org.tukaani.xz.XZInputStream(
new java.io.BufferedInputStream(
context.getAssets().open("file.xz"),
/* compressed size here */)).read(data);
然而,这对 6 秒的延迟没有明显影响(因此评论似乎是正确的:无论哪种方式,性能都一样糟糕)。