Android中的ABI

作者: daking | 来源:发表于2017-08-01 21:44 被阅读1478次

Android中的ABI

  • ABI是Application Binary Interface的缩写。

  • ABI常表示两个程序模块之间的接口,且其中一个模块常为机器码级别的library或操作系统。

  • ABI定义了函数库的调用、应用的二进制文件(尤其是.so)如何运行在相应的系统平台上等细节。

  • Android目前支持以下七种ABI:armeabi、armeabi-v7a、arm64-v8a、x86、x86_64、mips、mips64

Android中的CPU

  • 不同的Android设备使用支持不同指令集的CPU。

  • Android目前有以下七种cpu架构:ARMv5、ARMv7、ARMv8、x86、x86_64、MIPS和MIPS64

Android中的ABI与CPU

  • 每种CPU架构都有其自己支持的ABIs。可通过Build.SUPPORTED_ABIS得到根据偏好排序的设备支持的ABI列表。
CPU(纵向)/ABI(横向) armeabi armeabi-v7a arm64-v8a x86 x86_64 mips mips64
ARMv5 支持(1)
ARMv7 支持(2) 支持(1)
ARMv8 支持(3) 支持(2) 支持(1)
x86 支持(3) 支持(2) 支持(1)
x86_64 支持(4) 支持(3) 支持(2) 支持(1)
MIPS 支持(1)
MIPS64 支持(2) 支持(1)

表中的数字表示最终选择安装的ABI的优先级,1为最高。

  • 每种CPU架构都有自己对应的最优ABI。
CPU架构 最优ABI
ARMv5 armeabi
ARMv7 armeabi-v7a
ARMv8 arm64-v8a
x86 x86
x86_64 x86_64
MIPS mips
MIPS64 mips64
  • 应用安装到设备时,只有该设备的CPU架构支持的最优so库才会被安装。

    如:x86架构的设备支持x86、armeabi-v7a和armeabi等ABI。但优先级从高到低依次为x86、armeabi-v7a、armeabi。系统会根据此顺序寻找首个可用的最优的so库,找到则结束。

  • x86设备包含ARM模拟层,能够很好地运行ARM类型的so库,但并不保证100%不发生Crash。

  • 64位设备(arm64-v8a, x86_64, mips64)能够运行32位的so库。但是以32位模式运行时,会丢失专为64位优化过的性能特征(ART, WebView, Media, etc.)。

NDK兼容性

  • NDK平台不是向后兼容(兼容过去的版本)的,而是向前兼容(兼容未来的版本)的。

  • NDK编译的版本应该尽量使用较低的版本,如minSdkVersion="8"。

Android中的so库

so库的名称和文件名

  • so库的名称可任意,如daking。

  • so库的文件名必须以lib开头。如libdaking.so,其中lib是必要前缀,daking才是这个库的名称。

so库文件的路径

  • 在Android Studio中的路径:

    默认要放在模块/src/<SourceSet>/jniLibs/<ABI>/下。如:将so库放在app/src/main/jniLibs/armeabi

    可在模块的build.gradle中修改配置指定so库的路径。如,将so库放在app/libs/armeabi下,并修改配置如下:

 android {
  ...
  sourceSets {
    main {
      jniLibs.srcDirs = ['libs']
    }
  }
}
  • 在Eclipse中的路径:

    放在libs/<ABI>下。

  • 在Android系统中的路径:

    /data/data/<应用包名>/lib/下。

  • 在aar包中的路径:

    jni/<ABI>下。

so库的代码加载

  • System.loadLibrary("so库的名称");如System.loadLibrary("daking");会加载该应用下的libdaking.so文件。

  • System.load("so库文件的全路径");如System.load("/data/data/com.daking.app.demo/libdaking.so");会加载包名为com.daking.app.demo的应用的libdaking.so文件。

so库的使用建议

  • 理论上应该为每个ABI目录提供对应的so库。但是Android支持7种ABI,若全部支持,必然导致APK包过大。

  • 一般只保留armeabi、armeabi-v7a这两个ABI的so库。

    mips/mips64:极少用于手机,可忽略。

    x86/x86_64:x86架构的手机的市场占有率很低,约为1%左右。而且x86架构都包含ARM模拟层,兼容ARM类型的ABI。注意,模拟器为x86架构。

    arm64-v8a:64位ARM架构。可用32位模式运行armeabi-v7a和armeabi。

    armeabi-v7a:截止于2017年2月,目前主流版本AMRv7。

    armeabi:老版本ARMv5,但仍需要兼容。

  • 通过上面的分析,不难发现,只要提供armeabi便可兼容新/旧设备。但armeabi缺少对浮点数机器的支持,存在性能瓶颈。应该将armeabi目录中的so库拷贝一份到armeabi-v7a目录中。

  • 总结:

    为了减小apk体积,只保留armeabi和armeabi-v7a两个目录,并保证这两个目录中so库数量一致。

    对只提供armeabi版本的第三方so库,原样复制一份到armeabi-v7a目录中。

so库的常见错误

  • 使用高版本编译出的so库运行在低版本的平台上会出错。考虑到NDK是向前兼容的,应使用低版本编译。

  • so库放置的路径有误。

  • 没有在每个生效的ABI目录下放置对应的so库。

    1. 若某应用有armeabi和arm64-v8a两个ABI目录,armeabi目录里有a.sob.so,但arm64-v8a只有a.so
    2. 当ARMv8设备在安装此应用时,根据ABI优先级,首先发现arm64-v8a目录存在,并决定使用此ABI下的so库。
    3. 但arm64-v8a目录中没有b.so,于是报错。
    4. 此时的解决方案有:一,删除arm64-v8a目录;二,arm64-v8a目录的so库情况要与armeabi一致。

工具

  • Native Libs Monitor,监控设备上所有已安装的App,列出它们apk中包含的so库以及检测出最终安装到的so库。

我的博客

相关文章

网友评论

  • corabsins:第一优先级、第二优先级这个不靠谱,官网也没有这方面的介绍 ,这么说吧,一般设备都有主ABI 和 辅ABI 之分,会优先匹配主ABI ,找不到才会找辅ABI ,都找不就肯定报错

    比如说一个设备主ABI 是x86_64 ,辅ABI 是 armV7 , 而代码中支持了armeabi 和 x86 ,首先找主ABI x86_64 没有找到,它不会按你说的优先级 找x86, 找的是armeabi ,不相信的可以用小米pad 2验证下

    反解大厂的的apk 看下,基本就支持了arm ,为什么呢 ?因为1,主流架构就是arm ,ndk 向前兼容性原则 使用armebai 就足够了,2、一般教育类的app 在平板上的用户量比率会多一些,而平板支持x86的比率也比较多一些,所以一般还要支持x86 , 但为什么 很多app 仍然只支持armeabi 呢 ?主要是因为 上面说的主、辅abi ,一般情况下,主abi 为x86的设备,都有辅abi arm ,所以只要 支持 armeabi 就足够了
    但有很特殊的情况,就是有的设备就只支持 x86 ,也就是没有辅abi arm ,如果要兼容这个设备,那就再加一个 x86 就行了,其它加了会增加apk 的体积

    关于主abi和辅abi ,官网有介绍,https://developer.android.com/ndk/guides/abis?hl=zh-cn
    corabsins:@daking armeabi 是第5、6代cpu架构 ,现在很少的机型还是此架构,如果不考虑这些设备,一般使用armv7,再加个x86就成了 。

    但一个app 用户量很多的情况下,armeabi 就还需要留下,如果要去掉,必须有相关的官方说明 ,一切用户至上。用户量很少、或者新的app ,可以不用考虑 。
    daking:@corabsins 谢谢指出我之前的错误哈。:grin: 是没有明确的abi优先级规范,我之前说的所谓abi优先级顺序只是刚好符合当前大多数设备的支持情况。:joy: 在代码中使用Build. SUPPORTED_ABIS能获取当前设备支持的abi列表,优先级高的在前面。NDK17+把arm等抛弃了,考虑到最终包的大小,一般来说包含armv7即可,若要支持平板和模拟器,加上x86。:smile: 感谢交流讨论,待我空闲,会改正重发。
    corabsins:顺便补充下,如果一个设备只有主abi x86_64 ,而我们支持了x86 和 armeabi ,它确实会按照你说的优先级顺序找 ,也就会到x86 中找 。如果该 设备还有辅abi arm ,找不到他就会到 辅abi 里找。
  • 熊熊雷火:介绍的很好,很多以前模模糊糊的都懂了,建议改下标题,搜索到的人会更多
  • d020c6ede300:写的非常好 赞:+1:

本文标题:Android中的ABI

本文链接:https://www.haomeiwen.com/subject/rvyslxtx.html