概述
关于CPU架构
CPU有MIPS、ARM、X86三大架构。其中包括:
1、armeabi系列:属于ARM (A7、A9、A15、A53、A57) 包含:高通、麒麟(华为海思)、澎湃(小米)、联发科、猎户座(三星Exynos)
2、mips系列:属于MIPS ,多用在网关、猫、机顶盒等。代表:中国“龙芯”
3、x86系列:pc模拟器、Intel Atom系列处理器(英特尔放弃应用于手机、PC、平板以及可穿戴设备的Atom处理器)
Android系统目前支持以下七种不同的CPU架构:ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起)。可以用命令cat /proc/cpuinfo查看手机CPU信息。
关于ABI
Android系统目前支持以下七种不同的ABI:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64。应用程序二进制接口(Application Binary Interface即ABI)定义了二进制文件(尤其是.so文件)如何运行在相应的系统平台上,从使用的指令集,内存对齐到可用的系统函数库。
CPU架构与ABI的关系
在Android系统上,每一个CPU架构对应一个ABI,我们可以简单的理解为:
一种CPU架构 = 一种对应的ABI类型 = 一种对应类型的SO库
CPU架构与ABI的对应关系如下表所示:
CPU架构 | 对应ABI | 厂商 | 位数 | 开始时间 | SUPPORTED_ABIS | 适用设备 |
---|---|---|---|---|---|---|
ARMv5 | armeabi | AMR | 32 | 2010以前 | armeabi | 早期的手机用的比较多 |
ARMv7 | armeabi-v7a | AMR | 32 | 2010 | armeabi-v7a,armeabi | 2011年12月以后生产的大部分Android设备都使用它 |
x86 | x86 | Intel | 32 | 2011 | x86,armeabi-v7a,armeabi | 平板、模拟器用得比较多 |
MIPS | mips | MIPS | 32 | 2012 | 极少用于手机,忽略 | 极少用于手机,多用于网关、猫,可以忽略 |
ARMv8 | arm64-v8a | AMR | 64 | 2014 | arm64-v8a,armeabi-v7a,armeabi | 第8代64位ARM处理器,目前大部分Android手机都使用它 |
MIPS64 | mips64 | MIPS | 64 | 2014 | 极少用于手机,忽略 | 极少用于手机,多用于网关、猫,可以忽略 |
x86_64 | x86_64 | Intel | 64 | 2014 | x86_64,x86,armeabi | 64位的平板 |
表1:CPU架构与ABI的对应关系表
怎样查看apk中的.so?
1、用Android Studio中 的 APK 分析器。
2、使用命令:zipinfo -1 YOUR_APK_FILE.apk | grep .so$
3、使用Native Libs Monitor
4、反编译APK,查看libs目录。
怎样查看设备支持的ABI?
通过Build.SUPPORTED_ABIS得到设备支持的ABI列表。
SO库的安装和加载
Android系统在安装APK的时候,不会安装APK里面全部的SO库文件,而是会根据当前CPU类型支持的ABI,从APK里面拷贝最合适的SO库,并保存在APP的内部存储路径的 libs 下面。SO库其实都是APP运行时加载的,也就是说APP只有在运行的时候才知道SO库文件的存在,这就无法通过静态代码检查或者在编译APP时检查SO库文件是否正常。所以,Android开发对SO库的存放路径有严格的要求。
尽可能提供CPU支持的最优SO库
当一个应用安装在设备上,只有该设备支持的CPU架构对应的SO库会被安装。但是,有时候,设备支持的SO库类型不止一种,比如大多的X86设备除了支持X86类型的SO库,还兼容ARM类型的SO库。
所以如果你的APK只适配了ARM类型的SO库的话,还是能以兼容的模式在X86类型的设备上运行(比如华硕的平板),但是这不意味着你就不用适配X86类型的SO库了,因为X86的CPU使用兼容模式运行ARM类型的SO库会异常卡顿(就像在PC上使用AVD模拟器一样)。
不要为了减少APK的体积而减少某些类型的SO库
所有的x86/x86_64/armeabi-v7a/arm64-v8a设备都支持armeabi架构的.so文件,有些APP为了减少APK大小,就只保留armeabi,而移除了其他ABI。但事实上这会影响到函数库的性能和兼容性。所以,最好是针对特定平台提供相应平台的二进制包,这种情况下运行时就少了一个模拟层(例如x86设备上模拟arm的虚拟层),从而得到最新架构带来的更好性能(如硬件fpu,更多的寄存器,更好的向量化等)。如:x86设备能够很好的运行ARM类型函数库,但并不保证100%不发生crash,特别是对旧设备。64位设备(arm64-v8a, x86_64, mips64)能够运行32位的函数库,但是以32位模式运行,在64位平台上运行32位版本的ART和Android组件,将丢失专为64位优化过的性能(ART,webview,media等等)。
减少APK体积可以用其它方法:
1、分包处理:通过配置Gradle,生成不同ABI支持的APK。
2、使用Android的动态加载技术,可以加载外部的SO库。
保证所有 ABI 目录下的so数目一致
如果需要提供多套 ABIs 的支持,就需要保证所有 ABI 目录下,对应的 so 文件保持一致。
如:64 位的 arm64-v8a 是可以向下兼容的,如果你的项目中,有 armeabi-v7a 和 arm64-v8a 两个目录,就需要保证这两个目录下支持的 so 库文件保持一致。
在左边的情况下,如果ARMv8 的手机用到 b.so 时,就会去 arm64-v8a 目录下找,当然是找不到 b.so 文件的,就会直接抛异常,而不会再去 armeabi-v7a 目录下继续寻找。实际项目中如果遇到第三方SDK是提供的b.so只有armeabi-v7a怎么办?那就把armeabi-v7a中的b.so原样复制一份到 arm64-v8a 文件夹,保证每个ABI文件夹中的.so数量一致。
如果我们的APP只支持armeabi-v7a和x86架构,然后我们的APP使用了一个第三方的Library,而这个Library提供了AMR64等更多类型CPU架构的支持,构建APK的时候,这些ARM64的SO库依然会被打包进APK里面,也就是说我们自己的SO库没有对应的ARM64的SO库,而第三方的Library却有。这时候,某些ARM64的设备安装该APK的时候,发现我们的APK里带有ARM64的SO库,会误以为我们的APP已经做好了AMR64的适配工作,所以只会选择安装APK里面ARM64类型的SO库,这样会导致我们自己项目的SO库没有被正确安装(虽然armeabi-v7a和x86类型的SO库确实存在APK包里面)。
这时正确的做法是,给我们自己的SO库也提供AMR64支持,或者不打包第三方Library项目的ARM64的SO库。使用第二种方案时,可以把APK里面不需要支持的ABI文件夹给删除,然后重新打包,而在Android Studio下,则可以通过以下的构建方式指定需要类型的SO库。
productFlavors {
flavor1 {
ndk {
abiFilters "armeabi-v7a"
abiFilters "x86"
abiFilters "armeabi"
}
}
flavor2 {
ndk {
abiFilters "armeabi-v7a"
abiFilters "x86"
abiFilters "armeabi"
abiFilters "arm64-v8a"
abiFilters "x86_64"
}
}
}
需要说明的是,如果我们的项目是SDK项目,我们最好提供全平台类型的SO库支持,因为APP能支持的设备CPU类型的数量,就是项目中所有SO库支持的最少CPU类型的数量(使用我们SDK的APP能支持的CPU类型只能少于等于我们SDK支持的类型)。
总结一下在项目中遇到的ABI兼容性表现就是:
如果项目只包含了 armeabi,那么在所有Android设备都可以运行; 如果项目只包含了 armeabi-v7a,除armeabi架构的设备外都可以运行; 如果项目只包含了 x86,那么armeabi架构、arm64-v8a架构和armeabi-v7a的Android设备是无法运行的; 如果同时包含了 armeabi, armeabi-v7a、arm64-v8a和x86,所有设备都可以运行,程序在运行的时候去加载不同平台对应的so,这是较为完美的一种解决方案,同时也会导致包变大。
一定要支持 64 位架构
由于目前主流Android手机都支持64位,且为了充分利用64位CPU架构的高性能,Google Play强制要求“从2019年8月1日起,上架的 App,除了提供 32 位的版本之外,还需要提供 64 位的版本”。
只需适配Android手机的APP需要兼容哪些ABI?
从表1:CPU架构与ABI的对应关系表中看出目前主流的Android手机是ARMv8、ARMv7架构,如果你的APP不需要适配平板,那么你的APP只需要保留arm64-v8a和armeabi-v7a。这样既能保证兼容几乎所有Android手机,又能保证APP有好的性能,且能减小APK的大小。
分包处理
为减少APK包大小,你可以选择在应用市场上传指定ABI版本的APK,生成不同ABI版本的APK可以在build.gradle中如下配置:
android {
...
splits {
abi {
enable true
reset()
include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' //select ABIs to build APKs for
universalApk true //generate an additional APK that contains all the ABIs
}
}
// map for the version code
project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9]
android.applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
output.versionCodeOverride =
project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode
}
}
}
参考文档
Android jniLibs下目录详解(.so文件)
与 .so 有关的一个长年大坑
使用SO库时需要注意的一些问题
关于Android的.so文件你所需要知道的
这一次谷歌很强硬,App 再不支持,两个月后将拒绝上架!
armeabi-v7a armeabi arm64-v8a
Android 开发打包时我们应该如何注意平台的兼容(x86,arm,arm-v7a)
安卓app打包的时候还需要兼容armeabi么?
说说Android项目中的armeabi,armeabi-v7a和x86
最后
以上就是风中音响为你收集整理的关于Android的.so文件的全部内容,希望文章能够帮你解决关于Android的.so文件所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复