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//jniLibs//下。如:将so库放在app/src/main/jniLibs/armeabi

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

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

    放在libs/下。

  • 在Android系统中的路径:

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

  • 在aar包中的路径:

    jni/下。

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库。

我的博客

更多相关文章

  1. Flutter之Android SDK版本与External Libraries中的Android API
  2. Android 基于高德地图路径规划
  3. 字符串资源多国语言版本的出错问题
  4. Android中Gradle配置打包运行不同版本

随机推荐

  1. SQL中的开窗函数详解可代替聚合函数使用
  2. SQL Server分隔函数实例详解
  3. SqlServer数据库中文乱码问题解决方法
  4. Mybatis4 之Mybatis动态sql的实现代码
  5. SQL Server 2017 Developer的下载、安装
  6. SQLServer2019安装教程图文详解
  7. SQL Server免费版的安装以及使用SQL Serv
  8. 何谓SQLSERVER参数嗅探问题
  9. SQL语句执行超时引发网站首页访问故障问
  10. 利用SQL Server触发器实现表的历史修改痕