博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【走过巨坑】android studio对于jni调用及运行闪退无法加载库的问题解决方案
阅读量:5015 次
发布时间:2019-06-12

本文共 5330 字,大约阅读时间需要 17 分钟。

相信很多小伙伴都在android开发中遇到调用jni的各种巨坑,因为我们不得不在很多地方用到第三方库so文件,然而第三方官方通常都只会给出ADT环境下的集成方式,而谷歌亲儿子android studio默认采用的却是gradle方式,与ADT编辑的方式大不相同,那再andorid studio中如何导入so文件呢?

 

在android studio 中我们可能会用到jar包和so文件的方式,对于jar包可能接触更多,只需要我们把工程转换为project显示方式,打开app下的libs文件夹,导入即可。随后再添加jar包为我们的工程依赖即可。

 

好吧,楼主不想跑题。对于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。而这些包的名字是不能随便更改的。

 

而我们在开发中,应该尽可能的得到每一种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并不全面,所以遇上这样的奇葩问题也是难免。

那么,到底如何解决呢?

楼主通过网上提供的一些解决办法说,可以在gradle中添加配置如下:

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 code13     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 output17         variant.outputs.each { output ->18             output.versionCodeOverride =19                     project.ext.versionCodes.get(output.getFilter(com.android.build.OutputFile.ABI), 0) * 1000000 + android.defaultConfig.versionCode20         }21     }22  }

 

可事实是:找不到包名!!到底什么鬼?

 

楼主在各种碰壁后,希望大家不要再在这种低级问题上碰的头破血流,楼主的解决方案是通过build.gradle设置让apk打包只打包armeabi包下的.so文件,

添加代码为:

1   2  3 android{ 4  5    ....... 6  7     defaultConfig { 8         ndk { 9             abiFilters 'armeabi'10         }11     }12 }

 

当然,这样虽然投机取巧在aremabi下的可以支持所有的CPU机型,但是无疑使用不到各种机型特定的性能优化,为了让其不会闪退,楼主也只能暂时采用此类方法。如果大家有更好的方法,也希望能在评论区共享,谢谢。

 转载请在醒目位置附上本文链接:

 

 

2017-03-06补充

如果你作这样的更改后依然不行的话,可能是你的.so文件采用了较低版本的SDK编译,此时通常可以将targetSdkVersion设置为22就可以解决了,如果还是不能解决,可以尝试继续降低targetSdkVersion的版本。

另外,楼主在后面专门更新了.so文件库的解读,可以去看看:

转载于:https://www.cnblogs.com/liushilin/p/5792505.html

你可能感兴趣的文章
Windows 2008 R2系统开机时如何不让Windows进行磁盘检测?
查看>>
WP7应用开发笔记(18) 本地化与多语言
查看>>
解决 .so文件64与32不兼容问题
查看>>
归并排序法
查看>>
spark开发生成EXE
查看>>
Vue 全家桶介绍
查看>>
Linux lsof命令 umount U盘
查看>>
CRC标准以及简记式
查看>>
SEO搜索引擎
查看>>
关于本地使用tomcat部署web应用,浏览器自动跳转为https的问题
查看>>
一、Text To Speech
查看>>
Java读取并下载网络文件
查看>>
github上构建自己的个人网站
查看>>
在word中粘贴的图片为什么显示不完整
查看>>
SQL Server 数据库的鼠标操作
查看>>
net软件工程师求职简历
查看>>
SQL SERVER BOOK
查看>>
JS基础回顾,小练习(判断数组,以及函数)
查看>>
多任务——进程
查看>>
WCF:如何将net.tcp协议寄宿到IIS
查看>>