【走過巨坑】android studio對於jni調用及運行閃退沒法加載庫的問題解決方案

相信不少小夥伴都在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文件)的一些看法

相關文章
相關標籤/搜索