简介:做项目的时候经常会使用到so文件。例如使用高德地图,其SDK中就包含了armeabi、armeabi-v7a、arm64-v8a、x86等其他文件夹,里面通常放着同样名称、同样数量的so文件。实际使用过程中,关于这些so文件引发的问题确实不少,也不好解决。写下此文,希望以后遇到相关的问题,能有个大概的思路。
名词解析:
NDK:Native Development Kit
JNI:Java Native Interface
ABI: Application Binary Interface 应用二进制接口
Android Studio使用so库
1、使用和eclipse一样在libs目录下新建armeabi目录的方式
需要在build.gradle中添加指定jni库目录的语句
sourceSets {
main.jniLibs.srcDirs = [‘libs‘] //指定libs为jni的存放目录
}
2、使用AS默认的位置:src/main/jniLibs
直接在src/main/下新建jniLibs目录,将armeabi等目录放到该目录下即可
备注:AS可以直接右键新建同目录下的jniLibs目录,但该目录不是编译好的库文件目录,而是未编译的本地代码文件的目录(这里指的是与java同级的jni目录,放置cpp代码的)
android支持的cpu架构(目前是七种)
armeabi | 第5代 ARM v5TE,使用软件浮点运算,兼容所有ARM设备,通用性强,速度慢 |
armeabi-v7a | 第7代 ARM v7,使用硬件浮点运算,具有高级扩展功能 |
arm64-v8a | 第8代,64位,包含AArch32、AArch64两个执行状态对应32、64bit |
x86 | intel 32位,一般用于平板 |
x86_64 | intel 64位,一般用于平板 |
mips | 少接触 |
mips64 | 少接触 |
安装时的兼容性检查:
安装到系统中后,so文件会被提取在:data/app/com.xxxxxxxx.app-x/lib/目录下(5.0版本)、/data/app-lib/目录下(4.2版本),其中armeabi和armeabi-v7a会生成arm目录,arm64-v8a会生成arm64目录。
安装app的时候,如果app使用了so文件,而不存在适合本机cpu架构的so文件,会报如下错误:
Installation failed with message INSTALL_FAILED_NO_MATCHING_ABIS.
例如:在x86模拟器上就必须有x86版本的so文件夹。不然无法安装成功。
运行时的兼容性检查:
1、检查目标目录下是否存在的so库文件
2、检查存在的so文件是否符合当前cpu架构。
对于情况一,一般规避的做法是:保证jnilibs目录下x86、x84_64、armeabi、armeabi-v7a、arm64-v8a等目录下的文件名称数量是一致的。
例如:项目中使用了A、B、C三个第三方库。其中A、B提供了armebi以及arm64-v8a版本的库文件,而C只提供了armebi、armebi-v7a版本的库文件。这时候只能够删除原有的arm64-v8a目录,保留armeabi目录,一般arm64的手机都能兼容使用armeabi版本的库。或者复制一份armeabi的so文件到缺少的目录中(推荐)。
生成so文件:
NDK交叉编译时选定APP_ABI := armeabi x86 ...可以生成支持相应芯片的so文件。APP_ABI := all生成支持所有芯片指令集(目前七种)so文件。
Android加载so文件规则:
当你只提供了armeabi目录时,armeabi-v7a、arm64-v8a架构的程序都会去armeabi里寻找,而当你同时也提供了armeabi-v7a、armeabi-v8a目录,而里面又不存在对应的so库时,系统就不会再去armeabi里面寻找了,直接找不到报错。其他平台也是如此。这里我踩了不少的坑,切记。
一般来说,一些比较有名的第三方库都会提供armeabi、armeabi-v7a、x86这三种类型的so文件,同时拥有这三种版本的app可以在所有机型上运行。另外,越来越多的SDK会同时提供arm64-v8a版本。只包含armeabi的项目也可以在所有设备上运行。
现实案例:
我的项目中使用了armeabi、arm64-v8a两种类型,而当我需要使用某语音第三方库的时候,发现只提供了armeabi、armeabi-v7a两种类型的so文件,而我的手机是arm64-v8a的。所以只会使用arm64-v8a里面的so文件,当使用到该语音库时找不到对应的so库,就会报错。理论上有以下两种解决方法:
一、删除所有arm64-v8a,只保留armeabi,全部使用兼容性最高的版本,但也运行速度最慢。
二、将该语音库的armeabi版本的so复制到arm64-v8a中。单一so文件使用armeabi兼容版本。
总结:
- 当你使用到so文件时,保证每个子文件夹中文件名称数量都是一致的。
- 对于只提供armeabi的第三方库,复制一份armeabi的so文件到缺失的其他目录中;或者只保留armeabi目录(不推荐)
参考文档:
Android 关于arm64-v8a、armeabi-v7a、armeabi、x86下的so文件兼容问题