引用了一些第三方的sdk的so库之后通常都会遇到这样的错误,("nativeLibraryDirectories=[/data/app/com.lukouapp-1/lib/arm64, /vendor/lib64, /system/lib64]]] couldn't find "libxxxx.so")因为手机的机型不同,so库的开发公司也各不同,有的so库兼容各种机型,兼容android api 17~28,有的so库只支持api>21的(如虹软的ArcFace的sdk的so库),下面分情况总结以下:
1.android系统支持七种不同的CPU架构:ARMv5(armeabi.so),ARMv7 (从2010年起)(armeabi-v7a.so),x86 (从2011年起)(x86.so),MIPS (从2012年起)(mips.so),ARMv8(arm64-v8.so,高端机),MIPS64(mips64.so)和x86_64(x86_64.so) (从2014年起),每一种都关联着一个相应的ABI(Application Binary Interface应用二进制接口=编译好的二进制so库文件)
【armeabi,armeabi-v7a,x86,mips,arm64-v8a(64位设备),mips6464位设备),x86_6464位设备)这些都是指令集的统称】
mips和mips_64:MIPS架构是一种高性能的嵌入式CPU构架,其出发点是高性能,主要用于路由器、猫等
X86(32位),x86_64(64位)(该芯片由美国intel英特尔公司生产) 该构架的处理器已经广泛运用在PC领域,
armeabi,armeabi-v7a,arm64-v8a(都采用ARM架构,该芯片由英国ARM公司生产)全世界超过95%的智能手机和平板电脑都采用ARM架构,大部分android手机都是ARM架构的
1..1 所有的x86/x86_64/armeabi-v7a/arm64-v8a设备都支持armeabi架构的.so文件,armeabi-v7a 向下兼容 armeabi (大部分机器都属于armeabi-v7a),所以为减少apk的大小,一般一个armeabi-v7a.so就够了。第三方的sdk,提供了多少so库 ,你最好将它提供的都拷贝到项目中。android studio最好放在main/jniLibs(main下面没有jniLibs,就自己建一个)目录下,这样一般不会出问题,不建议自己指定ABI的路径。
2. so库文件里面大都是c/c++编写的代码,它们暴露原生native接口时需要指定应用的包名,故有些so库文件需要应用的包名要与so库开发商的给出的包名一致,【这一点开发商给的文档里一般都会说明,文档里没有,则可以忽略这个因素】
3.有的so库支持android api 17~28,有的so库只支持api>21的(如虹软的ArcFace的sdk的so库),当api较低的手机遇到这种情况时,最好拿api较高的,或别的手机测试一下,也可咨询一下开发商,该so库文件支持的手机api的版本
4.如果将so库文件其放在了libs下,则需要做如下配置:
sourceSets { main { jniLibs.srcDirs = ['libs'] } }
我的尝试配置:
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.lmj.lface"
minSdkVersion 14
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
ndk {
// 设置支持的SO库架构,第三方给的so库哪几种架构,就配置这几种架构
abiFilters 'armeabi' , 'armeabi','x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
}
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
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//指定so库的位置,加载so库
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
5.实在没有办法,还可做如下尝试:
gradle.properties中添加代码:
android.useDeprecatedNdk=true
在AndroidManifest.xml中添加代码
<application
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/provider_paths" />
</provider>
</application>
然后再res中新建xml/provider_paths.xml文件
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="external_files" path="."/>
<root-path
name="root_path"
path="." />
</paths>
如果还不行,那就删掉
1.删除c盘下的配置文件, 路径为C:\Users\用户名\.AndroidStudio1.2和C:\Users\用户名\.android两个文件夹,再重新断网打开android studio,碰到yes/no的选no,不要选择下载sdk,打开as后自己手动通过sdk manager指定原来的sdk即可,再次运行app【非常不建议这样做,并且也很可笑,但我就是这样解决了我的问题的,写在这里算是提供多一种的解决方案吧】,再此之前可多次clean project 再rebuild project
下方是引用别的博文的,也算是多提供一种思考吧:
世上本没有路,踩坑的多了就把路填平了。
一、UnsatisfiedLinkError基本介绍
全名 java.lang.UnsatisfiedLinkError
官方解释 Throw if the java Virtural Machine cannot find an appropriate native-language definition of method declared native意思就是JVM找不到native method的native实现!
抛出这异常,肯定是你加载SO的姿势不对!
现在App很多功能都是通过集成第三方工具实现的,第三方工具很有可能在SO动态库里实现核心功能(Bugly提供的libBugly.so,能捕获这类C/C++异常!),所以就算你不用NDK开发也一定会跟SO打交道,你确定你加载SO的姿势都对了吗?
二、错误场景分析
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设备
运行结果 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安装时,x86设备上系统会把apk中libs目录下x86的SO,拷贝到应用的私有目录下。虽然libs下有armeabi的SO,但没有放入x86的SO,运行时还是找不到libbugly.so。
修复方式 添加SO:libs\x86\libBugly.so或加载代码注释掉://System.loadLibrary(Bugly) ;
3、大坑——尼玛,好难发现!
code if(getArch().contain(“arm”)){//只在arm下加载System.loadLibrary(Bugly) ;System.loadLibrary(Bugly2);
}
libs libs\armeabi\libBugly.solibs\armeabi\libBugly2.solibs\armeabi-v7a\libBugly.so
运行设备 Android ARMv7设备
运行结果 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 “libBugly2.so”
原因分析 apk安装时,系统会把apk中libs目录下armeabi-v7a整个目录下的SO拷贝到应用的私有目录下。因为armeabi-v7a下没有放入libBugly2.so,运行时找不到libBugly2.so。不同的工具兼容的CPU架构不一致,就容易出这个错误了!例如:
libBugly.so提供armeabi、armeabi-v7a、x86三种。
但其它产品可能只提供了armeabi。
如果把这些so都直接拷贝进apk,就会因为上述的原因直接crash,会误以为该Crash是因为不同产品的so不能兼容导致的!
修复方式 添加SO:libs\armeabi-v7a\libBugly2.so或直接删除armeabi-v7a目录,arm设备上系统会自动选择armeabi
4、天坑——尼玛,巨难发现!
java.lang.UnsatisfiedLinkError中couldn’t find “XX.so”的占比非常高,上面提的三个场景都是这种错误!
但你见过下面这种错误吗?
java.lang.UnsatisfiedLinkError:dlopen failed: “**/*/arm/*.so” has unexpected e_machine: 3
这是天坑啊,肯定是实习生挖的!如何出现的呢?
code if(getArch().contain(“arm”)){//只在arm下加载System.loadLibrary(Bugly) ;}
libs libs\armeabi\libBugly.so 坑爹实习生放入了x86编译的libBugly.so(同名很容易出错)
运行设备 Android ARM设备
运行结果 Crash!java.lang.UnsatisfiedLinkError: dlopen failed: “/data/app/com.tencent.bugly.crashreport.demo-2/lib/arm/libBugly.so” has unexpected e_machine: 3
原因分析 apk安装时,系统把armeabi下的libBugly.so放入应用的私有目录中了!但这个libBugly.so不是arm的,而是x86编译的libBugly.so运行时,系统检察ELF文件中的e_machine字段的值,跟arm的不匹配,就会抛出这个异常了!
5 java.lang.UnsatisfiedLinkError:No implementation found for XXX
这种错误也是醉了,说是要建立跟c/cpp写的代码一样的包名和java文件
还是不能解决问题的,欢迎在下方留言,我们一起讨论解决。