Android jniLibs下目錄詳解(.so文件)


http://www.jianshu.com/p/b758e36ae9b5

最近又研究了一下,參考了一下:
三星/聯發科等處理器規格表  更新時間:2017年5月
手機CPU架構體系分類及各大廠商 PS:我摘抄的
分析:
CPU:MIPS、ARM、X86三大架構
armeabi系列:屬於ARM (A7、A9、A15、A53、A57) 包含:高通、麒麟(華為海思)、澎湃(小米)、聯發科、獵戶座(三星Exynos)
mips系列:屬於MIPS ,多用在網關、貓、機頂盒等。代表:中國“龍芯”
x86系列:pc模擬器、Intel Atom系列處理器(英特爾放棄應用於手機、PC、平板以及可穿戴設備的Atom處理器)
綜上所述(個人總結)
時間:2017.5.19
結果:"armeabi", "armeabi-v7a", "arm64-v8a"

//代碼:
android {
    defaultConfig { 
        //Nuance自動生成的庫文件夾中沒有我們所需的so文件,所以按照上面的邏輯,
        //就應該是阻止自動生成我們不需要的文件夾或者下載相關的so文件放到對應的文件夾下面。
        //加入需要生成的文件夾//armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64
        ndk { abiFilters "armeabi", "armeabi-v7a", "arm64-v8a" }// 其他忽略
    }
}

有興趣可以看一下:
armeabi-v7a、armeabi、arm64-v8a 之間的區別

  .
PS:如果只要結果,以下可以忽略,如果要深入,請繼續。

國際管理上圖說明


一圖詮釋Android的.so文件

1、了解.so文件的原因:

  上周末參加AndroidBus開發者論壇[上海站],《小紅書Android演進之路》(主講:桑明明)提到.so文件,保留jniLibs下armeabi-v7a就可以了,這樣就大大降低app的大小。這話是對的,因為我開發中也出現過這樣的情況,jniLibs下所有的文件丟失了,app就小了兩三兆(就一個友盟社會化分享)。but有bug(有的手機會崩潰)。保留一個試了,沒有崩潰,然后再網上各種惡補.so文件的知識,cpu架構。


2、Android開發中常見的指令集體系?

 指令集         廠商    位數 
x86(x86)            Intel    32
x86_64(Intel 64)       Intel    64
arm64-v8a(ARMV8-A)    AMR    64
armeabi(ARM v5)        ARM    32
armeabi-v7a(ARM v7)     ARM    32
mips             MIPS    32
mips64           MIPS    64

  • Intel 64 指令集在 x86基礎上擴展的
  • armabi 是針對舊的或者普通的ARM v5 CPU
  • armabi-v7a 是針對ARM v7 CPU
  • arm64-v8a 是針對最新的 ARM v8a CPU的。

    特別注意:x86指令集有兩種CPU位,既有32位的,也有64位的。

更多指令集知識

3、以下概念是整理加工出來的

  我的參考

4、Android系統每一個CPU架構對應一個ABI

  如上圖【一圖詮釋Android的.so文件】
  Android系統目前支持以下七種不同的CPU架構,每一種都關聯着一個相應的ABI。應用程序二進制接口(Application Binary Interface)定義了二進制文件(尤其是.so文件)如何運行在相應的系統平台上,從使用的指令集,內存對齊到可用的系統函數庫。

5、為什么你需要重點關注.so文件

  如果項目中使用到了NDK(類似於JDK,因為版權問題谷歌自行開發了NDK),它將會生成.so文件,因此顯然你已經在關注它了。如果只是使用Java語言進行編碼,你可能在想不需要關注.so文件了吧,因為Java是跨平台的。但事實上,即使你在項目中只是使用Java語言,很多情況下,你可能並沒有意識到項目中依賴的函數庫或者引擎庫里面已經嵌入了.so文件,並依賴於不同的ABI。例如,項目中使用RenderScript支持庫,OpenCV,Unity,android-gif-drawable,SQLCipher等,你都已經在生成的APK文件中包含.so文件了,而你需要關注.so文件。

6、查看手機cpu架構

    adb device  查看連接的設備,
    adb -s 192.168.56.101:5555 shell  進入手機的shell設置模式,
    cat /proc/cpuinfo  查看手機CPU信息


查看手機CPU信息的命令)


或者搜:本地庫監視器Native Libs Monitor(其包名:com.xh.nativelibsmonitor.app

  Android應用支持的ABI取決於APK中位於lib/ABI目錄中的.so文件,其中ABI可能是上面說過的七種ABI中的一種。
  很多設備都支持多於一種的ABI。例如ARM64和x86設備也可以同時運行armeabi-v7a和armeabi的二進制包。但最好是針對特定平台提供相應平台的二進制包,這種情況下運行時就少了一個模擬層(例如x86設備上模擬arm的虛擬層),從而得到更好的性能(歸功於最近的架構更新,例如硬件fpu,更多的寄存器,更好的向量化等)。
  我們可以通過Build.SUPPORTED_ABIS得到根據偏好排序的設備支持的ABI列表。但你不應該從你的應用程序中讀取它,因為Android包管理器安裝APK時,會自動選擇APK包中為對應系統ABI預編譯好的.so文件,如果在對應的lib/ABI目錄中存在.so文件的話。

7、由於.so文件出錯的情況

7.1、處理.so法則和系統的選擇

  處理.so文件時有一條簡單卻並不知名的重要法則:你應該盡可能的提供專為每個ABI優化過的.so文件,但要么全部支持,要么都不支持:你不應該混合着使用。你應該為每個ABI目錄提供對應的.so文件。
  當一個應用安裝在設備上,只有該設備支持的CPU架構對應的.so文件會被安裝。在x86設備上,libs/x86目錄中如果存在.so文件的話,會被安裝,如果不存在,則會選擇armeabi-v7a中的.so文件,如果也不存在,則選擇armeabi目錄中的.so文件(因為x86設備也支持armeabi-v7a和armeabi)。

7.2、常見crash(崩潰)系列

  當你引入一個.so文件時,不止影響到CPU架構。我從其他開發者那里可以看到一系列常見的錯誤,其中最多的是"UnsatisfiedLinkError","dlopen: failed"以及其他類型的crash或者低下的性能:使用android-21平台版本編譯的.so文件運行在android-15的設備上,使用NDK時,你可能會傾向於使用最新的編譯平台,但事實上這是錯誤的,因為NDK平台不是后向兼容的,而是前向兼容的。推薦使用app的minSdkVersion對應的編譯平台。這也意味着當你引入一個預編譯好的.so文件時,你需要檢查它被編譯所用的平台版本。

7.3、混合使用不同C++運行時編譯的.so文件

  .so文件可以依賴於不同的C++運行時,靜態編譯或者動態加載。混合使用不同版本的C++運行時可能導致很多奇怪的crash,是應該避免的。作為一個經驗法則,當只有一個.so文件時,靜態編譯C++運行時是沒問題的,否則當存在多個.so文件時,應該讓所有的.so文件都動態鏈接相同的C++運行時。這意味着當引入一個新的預編譯.so文件,而且項目中還存在其他的.so文件時,我們需要首先確認新引入的.so文件使用的C++運行時是否和已經存在的.so文件一致。

7.4、如果沒有為每個支持的CPU架構提供對應的.so文件

  這一點在前文已經說到了,但你應該真的特別注意它,因為它可能發生在根本沒有意識到的情況下。例如:你的app支持armeabi-v7a和x86架構,然后使用Android Studio新增了一個函數庫依賴,這個函數庫包含.so文件並支持更多的CPU架構。如友盟社會化分享jar包帶有各種.so文件,放在jniLibs下的對應文件夾中。

7.5、在我們發布app后

  會發現它在某些設備上會發生Crash,最終可以發現只有64位目錄下的.so文件被安裝進手機。
  解決方案:重新編譯我們的.so文件使其支持缺失的ABIs,或者設置:ndk.abiFilters 顯示指定支持的ABIs。(最后一點:如果你是一個SDK提供者,但提供的函數庫不支持所有的ABIs,那你將會搞砸你的用戶,因為他們能支持的ABIs必將只能少於你提供的。)

7.6、將.so文件放在錯誤的地方
  我們往往很容易對.so文件應該放在或者生成到哪里感到困惑,下面是一個總結:
  • Android Studio工程放在jniLibs/ABI目錄中(當然也可以通過在build.gradle文件中的設置jniLibs.srcDir屬性自己指定)
  • Eclipse工程放在libs/ABI目錄中(這也是ndk-build命令默認生成.so文件的目錄)
  • AAR壓縮包中位於jni/ABI目錄中(.so文件會自動包含到引用AAR壓縮包的APK中)
  • 最終APK文件中的lib/ABI目錄中
  • 通過PackageManager安裝后,在小於Android 5.0的系統中,.so文件位於app的nativeLibraryPath目錄中;在大於等於Android 5.0的系統中,.so文件位於app的nativeLibraryRootDir/CPU_ARCH目錄中。
7.7、只提供armeabi架構的.so文件而忽略其他ABIs的

  所有的x86/x86_64/armeabi-v7a/arm64-v8a設備都支持armeabi架構的.so文件,因此似乎移除其他ABIs的.so文件是一個減少APK大小的好技巧。但事實上並不是:這不只影響到函數庫的性能和兼容性。x86設備能夠很好的運行ARM類型函數庫,但並不保證100%不發生crash,特別是對舊設備。64位設備(arm64-v8a, x86_64, mips64)能夠運行32位的函數庫,但是以32位模式運行,在64位平台上運行32位版本的ART和Android組件,將丟失專為64位優化過的性能(ART,webview,media等等)。

6.7、以減少APK包大小為由是一個錯誤的借口

  因為你也可以選擇在應用市場上傳指定ABI版本的APK,生成不同ABI版本的APK可以在build.gradle中如下配置:

android {

    ... 

    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
        }
    }
 }

.



作者:博麟Android
鏈接:http://www.jianshu.com/p/b758e36ae9b5
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

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



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