AAR 生成方法


使用第三方庫出現找不到so庫UnsatisfiedLinkError錯誤的原因以及解決方案
字數1563 閱讀913 評論2 喜歡2

在開發項目的時候我們免不了使用一些第三方的庫來進行快速開發,有些第三方庫只是簡單的一個jar包,但是有些使用了jni開發,因此會包含so庫文件,這個時候如果不消息我們就會遇到一個錯誤:java.lang.UnsatisfiedLinkError;

最近經常遇到有開發者在問使用環信sdk的時候出現這個錯誤;這里分享下問題原因以及解決方案;
首先這邊引用環信工程師總結的出現這個問題的一些原因(稍作排版修改):
導致產生UnsatisfiedLinkError的幾個原因

原文地址:UnsatisfiedLinkError錯誤分析
相關信息

hyphenatechatsdk提供的指令集類型僅提供armeabi、arm64-v8a、x86三種;

這里需要解釋一下相關信息:
armeabi和armeabi-v7a是相近似的指令集,v7a是增強型指令集,運行速度,效率均有所提高,他們都是32位指令,並且兼容;arm64-v8a對應arm64位指令集;
arm64位策略和intel IA32不一樣:intel64位指令是兼容intel32位指令,intel32位指令編譯的程序可以直接在intel64位機器上運行;但是arm不是,arm64位和arm32位是彼此獨立的指令系統,不兼容;arm這樣設計的原因是因為運行在嵌入式上,設計指標更趨向於效率,和耗電考量;實際上arm64位芯片上同時包含着arm64指令處理器和arm32位指令處理器,只不過兩個處理器彼此獨立;

影響鏈接的限制條件
armeabi的so實際上可以運行在arm64位機器上,只不過Google增加了限制條件:

    Android4.x只要能找到so,就可以運行,so可以在armeabi、armeabi-v7a、arm64-v8a,so位置可以很隨意;

    Android5.x開始,檢查更加嚴格,會只有和芯片型號對應目錄的so會安裝到手機中;

        舉個例子:
        開發環境下目錄結構如下
        libs/armeabi:libhyphenate.so libhyphenate_av.so
        libs/armeabi-v7a:libmediadata.so
        手機對應的指令集是armeabi-v7a,然后安裝到手機的只有libmediadata.so;

    Android6.x下,檢查更加嚴格,有一條規則,之前測試有遇到,現在不太確認;
    libs/armeabi/: libhyphenate.so libhyphenate_av.so
    libs/arm64-v8a(沒有此目錄)
    在arm64位機器上也可以運行,但是作為開發者通常會依賴其他開發包,比如baiduMap,也會用其他so,不能讓所有開發者都刪掉libs/arm64-v8a的目錄;不過開發者可以嘗試下刪除arm64-v8a,只留armeabi,這樣安裝包會很小,在各個平台上也能運行;
    Google考量點是執行速率,更流暢的用戶體驗,作為開發者,服務提供者,我們希望apk盡可能小,對執行速度要求不高;

    armeabi和armeabi-v7a可以互換,現在市面上的手機很少有armeabi的,基本上是armeabi-v7a或arm64位的高端機器。

    查看手機芯片型號:cat /proc/cpuinfo, 仔細看一下打印信息,能夠看明白手機指令集,是32位還是64位。

    x86目錄,通常對應虛擬機,很多開發者喜歡在genymotion上開發調試,這個就對應86,x86和前面說的intel IA32是一回事,所以只提供32位的,也能在x86-64位機器上運行;

    我們的so還依賴於libsqlite.so,不過由於這個包從來沒有變化,使用的是系統默認提供的/system/lib,在Android 6.x及以下的平台可以運行,Android7.x執行更嚴格的安全檢查,禁止使用系統目錄的內容,所以如果希望在Android7.x以上版本,需要把系統目錄的libsqlite.so拷貝出來,也放在自己app對應指令目錄下,由於目前Android7.x市面上沒有機型,所以目前不在考慮范圍;

    mips指令集的手機很少見,聽說聯想有出過,沒見過;

    libs/armeabi/libhyphenate.so和libs.without.audio/armeabi/libhyphenate.so是不同,libs/armeabi/libhyphenate.so會依賴於libs/armeabi/libhyphenate_av.so,如果找不到會報java.lang.UnsatisfiedLinkError;

    還有一個比較容易忽略的一點,現在我們的的項目一般都是引入好多個第三方庫,第六點也提到了使用baiduMap這點,就是當一個項目引入多個庫,不同的庫有不同的so文件夾,當其中一個支持的比較少,但是另一個比較全時,也會出現這樣的錯誤,解決方法就是不支持的so文件夾刪除

        舉例:
        環信支持的指令集arm64-v8a、armeabi、x86
        百度地圖支持的指令集arm64-v8a、armeabi、armeabi-v7a、x86、x86_64、mips、mips64
        如果想在所有設備上都能運行,需要把armeabi-v7a、x86_64、mips、mips64這些刪除;
        根據前邊所說可以保留armeabi-v7a文件夾,然后復制armeabi里的so文件到armeabi-v7a就行了

所以如果大家再遇到這樣的問題,可以先根據以上信息排查下,如有問題歡迎指正


 

那么問題來了,到底是什么原因呢?

通過分析crash日志,我發現一個問題:

    nativeLibraryDirectories=[/data/app/xxx-1/lib/arm64, /data/app/xxx-1/base.apk!/lib/arm64-v8a, /vendor/lib64, /system/lib64]

我外部的lib里並沒有那么多文件夾啊!!!!

這個就是crash的原因所在了。

當AAR內部的so文件類型比外部多時,會導致外部的so文件找不到。

所以果斷的剔除了AAR中不需要的so文件夾“arm64”,“arm64-v8a”,“x86”。

再次編譯,OK,齊活了。88,希望能幫助到你們。

文/13itch(簡書作者)
原文鏈接:http://www.jianshu.com/p/7e37b76ae39a
著作權歸作者所有,轉載請聯系作者獲得授權,並標注“簡書作者”。

dependencies {  

    compile fileTree(dir: 'libs', include: ['*.jar'])  

    testCompile 'junit:junit:4.12'  

    compile 'com.android.support:appcompat-v7:23.4.0'  

    compile(name: 'mylib', ext: 'aar')  

} 

注意:在defaultConfig中不要定義applicationId,因為aar是庫,無applicationId


2.如何在工程中導入aar?
(1)將編譯好的aar文件放到libs下,類似jar的做法。譬如,libs/mylib.aar。
(2)在工程的build.gradle中添加:






在CODE上查看代碼片派生到我的代碼片




    repositories{  

        flatDir {  

            dirs 'libs'  

        }  

    }  

 


 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM