Java Failure [INSTALL_FAILED_INVALID_APK: Failed to extract native libraries, res=-2]

咚咚 · March 11, 2019 · 4637 hits

Failure [INSTALL_FAILED_INVALID_APK: Failed to extract native libraries, res=-2]

第一次遇到这个报错,表示三脸懵逼,还以为是原始so文件有问题。

话不多说,我们来看看到底是什么问题呢~~~

extractNativeLibs

首先,需要弄明白extractNativeLibs是什么?

以下为官方说法:

android:extractNativeLibs
Whether or not the package installer extracts native libraries from the APK to the filesystem. If set to false, then your native libraries must be page aligned and stored uncompressed in the APK. No code changes are required as the linker loads the libraries directly from the APK at runtime.
The default value is "true".

百度翻译结果:
包安装程序是否将本地库从APK提取到文件系统。如果设置为false,那么您的本机库必须是页面对齐的,并且未在apk中压缩存储。当链接器在运行时直接从APK加载库时,不需要更改代码。
默认值为“真”。

为什么有 extractNativeLibs 呢?

在 Android 6.0 之前,代码中的 so 文件会被压缩到 apk 中,系统在安装 apk 的时候,会把 so 文件解压到 /data/app/ 中,这样同一个 so 文件就会有两份,一份在 apk 中压缩存储,一份在 /data/app/ 中未压缩存储,导致多占用了空间。 从 Android 6.0 开始,引入了extractNativeLibs,这样就可以去根据需要选择压缩或者不压缩。

extractNativeLibs 作用呢?

1、设置为 false 
则安装apk时告诉「系统」,不要把 so 文件从 apk 中解压出来了,同时修改 System.loadLibrary 直接打开调用 apk 中的 so 文件。

!!!但是,目前要让该技巧生效还需要额外2个条件:
Aapk 中的 .so 文件不能被压缩。
B.so 必须用zipalign -p 4来对齐。

缺点:apk 大小将变大


说明:
1、针对 Android 6+,如果 extractNativeLibs 设置为 false so 未压缩,将阻止您安装未对齐 APK,并提示:「Failure [INSTALL_FAILED_INVALID_APK: Failed to extract native libraries, res=-2]」。旧版的安卓并不关心,总是提取本地库,即使未对齐也可以安装。
2google市场的要求不管是否对 so 文件做压缩,都要做zipalign对齐才能上传。
3、从android studio 2.2 preview 2 和最新的构建工具开始,构建过程将自动存储未压缩的本机库,并在apk中对齐页面。不管是否对 so 进行压缩,都会做对齐的操作。

2、设置为 true
会压缩 so 文件,且安装 apk 时告诉「系统」,把 so 文件从 apk 中解压出来。

优点:较小的apk大小,因为库是压缩的
缺点:
A、增加了在手机上安装大小,因为除了APK之外,提取的本机库还占用了磁盘空间。
B、安装时间更长
3、未添加该属性到 AndroidManifest.xml 中,即使用默认值时
会自动去压缩 so 文件(除非一些引入库是可能导致问题,如objectbox

Apktool 导致 extractNativeLibs=false 的问题

如果 AndroidManifest.xml 中未设置 extractNativeLibs=true,使用 apktool 反编译时有可能导致 extractNativeLibs被设置未false。
(有两个产品工程,默认都不设置extractNativeLibs,但是一个会被设置为 false,一个不会。此处还需调查)并且,使用 apktool 反编译再回编译出来的 apk 是 不对齐的,需要自己做对齐操作。

接着上面,如何自己做对齐工作?

使用 zipalign 做对齐操作,有4或者8字节对齐,需要先确认 原始包是 4或者8。

1、如果用 apksigner 做签名,则需要先用 zipalign 做对齐,然后再签名。
2、如果用 jarsigner 做签名,则需要先签名,再做对齐。

具体操作:
1、检查对齐方式:zipalign -c -v 4 old.apk (4或者8)
2、做对齐:zipalign -v 4 old.apk new.apk (4或者8)
自己验证过程中的一些记录

两个工程的对比数据:

较详细的对比数据

待解决的疑问:
1、对齐方式确认,对齐方式应该有问题
2、为啥工程1、2有区别,为啥一个会使默认值变成false,一个不会;一个压缩,一个未压缩。
===〉调查下来是因为我们引入的库objectbox导致的,而且这个库使用的是没有压缩的so
===〉https://github.com/objectbox/objectbox-java/issues/665

参考链接:
https://stackoverflow.com/questions/42998083/setting-androidextractnativelibs-false-to-reduce-app-size
https://github.com/iBotPeaches/Apktool/issues/1626

No Reply at the moment.
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up