android开发 加载so库的解析和出现的各种错误分析,人生转折

=========================

很多设备都支持多于一种的ABI。例如ARM64和x86设备也可以同时运行armeabi-v7a和armeabi的二进制包。但最好是针对特定平台提供相应平台的二进制包,这种情况下运行时就少了一个模拟层(例如x86设备上模拟arm的虚拟层),从而得到更好的性能(归功于最近的架构更新,例如硬件fpu,更多的寄存器,更好的向量化等)。

五.如何查看当前设备支持那些版本的so库?

=====================

我们可以通过Build.SUPPORTED_ABIS得到根据偏好排序的设备支持的ABI列表。但你不应该从你的应用程序中读取它,因为Android包管理器安装APK时,如果在对应的lib/ABI目录中存在.so文件的话,会自动选择APK包中为对应系统ABI预编译好的.so文件。

六.不同的开发环境so库应该放在哪里?

===================

  • Android Studio工程放在jniLibs/ABI目录中(当然也可以通过在build.gradle文件中的设置jniLibs.srcDir属性自己指定)

  • Eclipse工程放在libs/ABI目录中(这也是ndk-build命令默认生成.so文件的目录)

  • AAR压缩包中位于jni/ABI目录中(.so文件会自动包含到引用AAR压缩包的APK中)

  • 最终APK文件中的lib/ABI目录中

  • 通过PackageManager安装后,在小于Android 5.0的系统中,.so文件位于app的nativeLibraryPath目录中;在大于等于Android 5.0的系统中,.so文件位于app的nativeLibraryRooandroid开发 加载so库的解析和出现的各种错误分析,人生转折
    tDir/CPU_ARCH目录中。

七.为什么一般的项目中只看到armeabi文件夹?

=========================

因为所有的x86/x86_64/armeabi-v7a/arm64-v8a设备都支持armeabi架构的.so文件。

八.那我们是不是只放一种armeabi就够了?

=======================

事实上并不是:这不只影响到函数库的性能和兼容性。x86设备能够很好的运行ARM类型函数库,但并不保证100%不发生crash,特别是对旧设备。64位设备(arm64-v8a, x86_64, mips64)能够运行32位的函数库,但是以32位模式运行,在64位平台上运行32位版本的ART和Android组件,将丢失专为64位优化过的性能(ART,webview,media等等)。

九.如何查看我的android手机属于什么架构的?

=========================

进入命令行:

第一步:输入 adb shell 回车

第二步:cat /proc/cpuinfo 回车

下面打印出的信息里面有 Processor 如下图:

android开发 加载so库的解析和出现的各种错误分析,人生转折

十.到底如何适配,每种适配方案区别?

==================

CPU之间的架构兼容

ARMv5 设备:只支持armeabi

ARMv7 设备:支持 armeabi 和 armeabi-v7a

ARMv8 设备:支持 armeabi-v7a、armeabi 和 arm64-v8a

X86 设备:支持 armeabi(性能有所损耗) 和 x86

x86_64 设备:支持 x86 和 x86_64

mips 设备: 支持 mips

mips_64 设备:支持 mips 和 mips_64

Android中设备加载so策略

不同CPU架构的android手机加载时会在libs下找自己对应的目录,从对应的目录下寻找需要的.so文件;如果没有对应的目录,就会去armeabi下去寻找,如果已经有对应的目录,却如果没有找到对应的.so文件,也不会去armeabi下去寻找了。

以x86设备为例,x86设备会在项目中的 libs文件夹寻找是否含有x86文件夹,如果含有x86文件夹,则默认为该项目有x86对应的so可运行文件,只有x86文件夹而文件夹下没有so,程序运行也是会出现find library returned null的错误的;如果工程本身不含有x86文件夹,则会寻找armeabi或者armeabi-v7a文件夹,兼容运行。以armeabi-v7a设备为例,该Android设备当然优先寻找libs目录下的armeabi-v7a文件夹,同样,如果只有armeabi-v7a文件夹而没有 so也是会报错的;如果找不到armeabi-v7a文件夹,则寻找armeabi文件夹,兼容运行该文件夹下的so,但是不能兼容运行x86的so。所以项目中如果只含有x86的so,在armeabi和armeabi-v7a也是无法运行的。以上就是不同CPU架构运行时加载so的策略。

目前主流的Android设备主要是 armeabi-v7a 架构的,然后是 x86 和 armeabi 了。如果同时包含了 armeabi, armeabi-v7a和x86,所有设备都可以运行,程序在运行的时候去加载不同平台对应的so,这是较为完美的一种解决方案,但是有时候为了减少apk的大小,不会同时设置 armeabi, armeabi-v7a 和 x86。根据不同的情况,可以进行不同的适配,

**1.只适配 armeabi-v7a,**因为目前主流机型是 ARMv7,并且 ARMv8 设备也向下兼容了armeabi-v7a,

Facebook、WhatsApp、王者荣耀等就是只适配了armeabi-v7a。(Google play store下载 Native libs Monitor 进行查看)。

2.只适配 armeabi,因为 ARMv7 、ARMv8 还是 x86 都兼容 armeabi,但是性能都会有些损耗,例如ARMv7 支持硬件浮点运算等没法体现,x86 支持 armeabi 同样具有相应的损耗。

3.同时适配 armeabi-v7a 和 armeabi,既能够支持所有 ARM 架构,同时又能具有 ARMv7 支持硬件浮点运算等特性,例如Line等应用

4.同时适配 x86 和 armeabi,既能支持所有 ARM 架构,又能支持x86架构,唯一的缺点就是没有了ARMv7 支持硬件浮点运算等一系列特性,例如QQ

5.同时适配 armeabi, armeabi-v7a 和 x86,在性能方面来说是较为完美的方案,只是APK的大小也会随之的变大

6.其他的一些方案,例如微信只适配了armeabi,但是对于某些需要利用 ARMv7 支持硬件浮点运算等一系列特性的操作,在armeabi目录下存在v7对应的so文件,通过代码判断加载不同的so文件。即达到了减少APK大小的目的,又能达到适配ARMv7等架构以便使用其架构的一些新特性的目的。

十一.so库开发过程中的一些错误汇总!(后续补充)

=========================

基本上大部分关于so库的错误 都是   java.lang.UnsatisfiedLinkError

官方解释     Throw if the java Virtural Machine cannot find an appropriate native-language definition of method declared native意思就是JVM找不到native method的native实现!

所以看到这个错误,一般常见的几种情况分析。

1、低级错误——根本木有SO,你加载个球啊!


code     System.loadLibrary(Bugly);

libs     空

运行设备     Android ARM设备

运行结果     Crash!java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/com.tencent.bugly.demo-1/base.apk”],nativeLibraryDirectories=[/vendor/lib, /systemb]]] couldn’t find “libBugly.so”

原因分析     apk安装时,系统会把apk中libs目录下armeabi的SO拷贝到应用的私有目录下。所以libs里没有放入SO,运行时肯定找不到SO。

修复方式     添加SO:libs\armeabi\libBugly.so或加载代码注释掉://System.loadLibrary(Bugly) ;

2、进阶错误——根本木有X86的SO,在X86的设备上你加载个球啊!


code     System.loadLibrary(Bugly);

libs     libs\armeabi\libBugly.so

运行设备     Android X86设备

ystem.loadLibrary(Bugly) ;

2、进阶错误——根本木有X86的SO,在X86的设备上你加载个球啊!


code     System.loadLibrary(Bugly);

libs     libs\armeabi\libBugly.so

运行设备     Android X86设备

上一篇:c – 使用VLC涂抹


下一篇:Spring5 - 向IOC容器中添加组件的4种方式