extractNativeLibs这个属性相信安卓开发者都不会陌生,先引用官方文档说明一下此属性的含义
android:extractNativeLibs
软件包安装程序是否将原生库从 APK 提取到文件系统。如果设为 false,则原生库必须保持页面对齐状态并以未压缩的形式存储在 APK 中。无需更改代码,因为链接器在运行时直接从 APK 加载库。
默认值为 "true"
含义比较明确,就是如果这个属性设置为 false
,那么 apk
的体积会变大,但是 apk
安装后系统会直接使用 apk
中的 so
,这样就节约了用户的存储空间。反之,如果这个属性设置为 true
,那么 apk
的体积会更小,因为 so
是压缩存储的,但是在 apk
安装的时候,系统会把 apk
中的 so
解压重新存储一份,导致占用的存储空间变大。
设置这个属性的方法就是直接在 AndroidManifest.xml
中声明即可。
<application
android:extractNativeLibs="true"
... >
</application>
如何确认apk
中so
是压缩存储的还是未压缩存储的呢,使用zipinfo
这个命令就行了
@debian-ts:~/tmp $ zipinfo test-store.apk *.so
-rw---- 2.4 fat 13776 b- stor 80-000-00 00:00 lib/armeabi-v7a/libtest.so
@debian-ts:~/tmp $ zipinfo test-deflate.apk *.so
-rw---- 2.4 fat 13776 b- defN 80-000-00 00:00 lib/armeabi-v7a/libtest.so
如果对 zip
压缩格式有了解的话就知道,stor
为不压缩存储,defN
为压缩存储。
官方文档上写明了默认值为 true
,这个没错,因为查看 系统源码 可以发现,读取这个属性的时候会以 true
作为默认值
if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestApplication_extractNativeLibs,
true)) {
ai.flags |= ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
}
如果在 AndroidManifest.xml
中主动设置了 android:extractNativeLibs
,那没得说肯定设置的是什么值就是什么值。但是如果默认没有设置,那就有讲究了。
从 AGP (Android Gradle Plugin) 的 CHANGELOG
中,我们可以看到,在 AGP 3.6.0 版本中,google
更新了 extractNativeLibs
的默认行为,在构建应用时,插件现在默认会将 extractNativeLibs 设置为 false
。
通过观察编译后生成的AndroidManifest.xml
文件,发现gradle
插件设置默认值为false
是通过在处理AndroidManifest.xml
文件的时候,在其中自动插入 android:extractNativeLibs=“false"
来实现的。但是由于 android:extractNativeLibs
这个属性是在 Android M(6.0)
引入的,所以如果项目中配置 minSdkVersion < 23
的话,gradle
插件是不会做这个自动插入的。
所以我们得出 extractNativeLibs
默认值的几种情况
条件 | 默认值 |
---|---|
AGP < 3.6.0 || minSdkVersion < 23 | true |
AGP >=3.6.0 && minSdkVersion >= 23 | false |