相信不少小伙伴都在android开发中遇到调用jni的各类巨坑,由于咱们不得不在不少地方用到第三方库so文件,然而第三方官方一般都只会给出ADT环境下的集成方式,而谷歌亲儿子android studio默认采用的倒是gradle方式,与ADT编辑的方式大不相同,那再andorid studio中如何导入so文件呢?html
在android studio 中咱们可能会用到jar包和so文件的方式,对于jar包可能接触更多,只须要咱们把工程转换为project显示方式,打开app下的libs文件夹,导入便可。随后再添加jar包为咱们的工程依赖便可。java
好吧,楼主不想跑题。对于so文件也很是简单,只须要在app/src/main下面创建一个jniLibs,再把咱们的第三方so文件拷贝进去便可,须要重点注意的是,咱们安卓通常有几种CPU,而再也不是之前的只有armv5,目前有7种。ARMv5,ARMv7 (从2010年起),x86 (从2011年起),MIPS (从2012年起),ARMv8,MIPS64和x86_64 (从2014年起),每一种都关联着一个相应的ABI。在Android系统上,每个CPU架构对应一个ABI:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64。而这些包的名字是不能随便更改的。android
而咱们在开发中,应该尽量的获得每一种ABI优化过的.so文件,而不该该混合着使用,其实为每一种ABI提供对应的.so文件其实也是SDK提供方应该作的,不过或许你不会这么好运,也许你的SDK提供方就会像和楼主遇到的同样,只给你提供一个armeabi方式的.so文件,额,是的,你写一个小demo测试SDK的功能多是可用的,而后当你把你写的demo引入到你的项目中后,你或许总能遇到这样那样的问题,好比,最多见的就是UnsatisfiedLinkError,固然你还可能遇到dlopen: failed以及其它各类形式的crash或者低下的性能。而你或许在有的手机上运行倒是不报任何错误的。好比楼主获得的第三方SDK,只提供了armeabi下的so文件,楼主导入到项目中后,(楼主项目以前支持了arm64-v8a等其余方式的ABI)使用相对版本老一点的手机运行,Ok,no problem!然而当用到小米系列的任何一款手机的时候,运行,直接Crash,缘由在初始化的时候直接找不到某些.so文件,致使没法使用System.loadLabray的方式加载,不知道赶上的小伙伴是怎么解决的,不过就这么一个问题,让楼主和一些一样的开发人员也是抓破了脑壳,楼主是知其缘由,而不知其解决方案,这是最使人头疼的。性能优化
下面是android studio的报错信息。架构
08-21 11:12:48.413 7971-7971/com.hkyc.shouxinteacher.ischool E/AndroidRuntime: FATAL EXCEPTION: main Process: com.hkyc.shouxinteacher.ischool, PID: 7971 java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.hkyc.shouxinteacher.ischool-2/base.apk"],nativeLibraryDirectories=[/data/app/com.hkyc.shouxinteacher.ischool-2/lib/arm64, /vendor/lib64, /system/lib64]]] couldn't find "libgnustl_shared.so" at java.lang.Runtime.loadLibrary(Runtime.java:366) at java.lang.System.loadLibrary(System.java:988) at com.idtechinfo.shouxiner.App.onCreate(App.java:92) at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1012) at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4580) at android.app.ActivityThread.access$1500(ActivityThread.java:154) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1376) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5283) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
好吧,真真使人头疼,楼主采用了各类解决方式都没有解决,由于android studio默认是会把全部ABI支持都打包到apk的,因为楼主获得的第三方SDK并不全面,因此赶上这样的奇葩问题也是不免。app
那么,到底如何解决呢?ide
楼主经过网上提供的一些解决办法说,能够在gradle中添加配置以下:oop
1 android { 2 ... 3 splits { 4 abi { 5 enable true 6 reset() 7 include 'x86', 'x86_64', 'armeabi-v7a', 'arm64-v8a' //select ABIs to build APKs for 8 universalApk true //generate an additional APK that contains all the ABIs 9 } 10 } 11 12 // map for the version code 13 project.ext.versionCodes = ['armeabi': 1, 'armeabi-v7a': 2, 'arm64-v8a': 3, 'mips': 5, 'mips64': 6, 'x86': 8, 'x86_64': 9] 14 15 android.applicationVariants.all { variant -> 16 // assign different version code for each output 17 variant.outputs.each { output -> 18 output.versionCodeOverride = 19 project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode 20 } 21 } 22 }
可事实是:找不到包名!!到底什么鬼?post
楼主在各类碰壁后,但愿你们不要再在这种低级问题上碰的头破血流,楼主的解决方案是经过build.gradle设置让apk打包只打包armeabi包下的.so文件,性能
添加代码为:
1 2 3 android{ 4 5 ....... 6 7 defaultConfig { 8 ndk { 9 abiFilters 'armeabi' 10 } 11 } 12 }
固然,这样虽然投机取巧在aremabi下的能够支持全部的CPU机型,可是无疑使用不到各类机型特定的性能优化,为了让其不会闪退,楼主也只能暂时采用此类方法。若是你们有更好的方法,也但愿能在评论区共享,谢谢。
转载请在醒目位置附上本文连接:http://www.cnblogs.com/liushilin/p/5792505.html
2017-03-06补充
若是你做这样的更改后依然不行的话,多是你的.so文件采用了较低版本的SDK编译,此时一般能够将targetSdkVersion设置为22就能够解决了,若是仍是不能解决,能够尝试继续下降targetSdkVersion的版本。
另外,楼主在后面专门更新了.so文件库的解读,能够去看看:【开发必备】今天咱们来谈谈Android NDK动态连接库(so文件)的一些看法