Android .SO 檔案的相容和適配

Kaitiren發表於2017-09-26

開發 Android 應用時,有時候 Java 層的編碼不能滿足實現需求,就需要到 C/C++實現後生成 SO 檔案,再用 System.loadLibrary()載入進行呼叫,這裡成為 JNI 層的實現。常見的場景如:加解密演算法,音視訊編解碼等。在生成 SO 檔案時,需要考慮適配市面上不同手機 CPU 架構,而生成支援不同平臺的 SO 檔案進行相容。目前 Android 共支援七種不同型別的 CPU 架構,分別是:ARMv5,ARMv7 (從 2010 年起),x86 (從 2011 年起),MIPS (從 2012 年起),ARMv8,MIPS64 和 x86_64 (從 2014 年起)。如果你要完美相容所有型別的手機,理論上是要在的 libs 目錄下放置各個架構平臺的 SO 檔案。

這樣一來,雖然可以相容所有機型,但你的專案體積也會變得非常龐大。是否一定需要帶入這麼多 SO 檔案去相容呢?答案是否定的。

SO(CPU)的相容

對於 CPU 來說,不同的架構並不意味著一定互不相容,根據目前 Android 共支援七種不同型別的 CPU 架構,其相容特點可總結如下:

  • armeabi 裝置只相容 armeabi;
  • armeabi-v7a 裝置相容 armeabi-v7a、armeabi;
  • arm64-v8a 裝置相容 arm64-v8a、armeabi-v7a、armeabi;
  • X86 裝置相容 X86、armeabi;
  • X86_64 裝置相容 X86_64、X86、armeabi;
  • mips64 裝置相容 mips64、mips;
  • mips 只相容 mips;

根據以上的相容總結,我們還可以得到一些規律:

  • armeabi 的 SO 檔案基本上可以說是萬金油,它能執行在除了 mips 和 mips64 的裝置上,但在非 armeabi 裝置上執行效能還是有所損耗;
  • 64 位的 CPU 架構總能向下相容其對應的 32 位指令集,如:x86_64 相容 X86,arm64-v8a 相容 armeabi-v7a,mips64 相容 mips;

關於 SO 的相容規律就介紹到此,下面談談適配工作。

SO 的適配

從目前移動端 CPU 市場的份額資料看,ARM 架構幾乎壟斷,所以,除非你的使用者很特殊,否則幾乎可以不考慮單獨編譯帶入 X86、X86_64、mips、mips64 架構 SO 檔案。除去這四個架構之後,還要帶入 armeabi、armeabi-v7a、arm64-v8a 這三個不同型別,這對於一個擁有大量 SO 檔案的應用來說,安裝包的體積將會增大不少。

針對以上情況,我們可以應用的裝置分佈和市場情況再進行取捨斟酌,如果你的應用仍有不少 armeabi 型別的裝置,可以考慮只保留 armeabi 目錄下的 SO 檔案(萬金油特性)。但是,儘管 armeabi 可以相容多種平臺,仍有些運算在 armeabi-v7a、arm64-v8a 去使用 armeabi 的 SO 檔案時,效能會非常差強人意,所以還是應該用其對應平臺架構的 SO 檔案進行運算。注意,這裡並不是要帶多一整套 SO 檔案到不同的目錄下,而是將效能差異比較明顯的某個 armeabi-v7a、arm64-v8a 平臺下的 SO 檔案放到 armeabi 目錄,然後通過程式碼判斷裝置的 CPU 型別,再載入其對應架構的 SO 檔案,很多大廠的應用便是這麼做的。如微信的 lib 下雖然只有 armeabi 一個目錄,但目錄內的檔案仍放著 v5、v7a 架構的 SO 檔案,用於處理相容帶來的某些效能運算問題。

就目前市場份額而言,絕大部分的裝置都已經是 armeabi-v7a、arm64-v8a,你也可以考慮只保留 armeabi-v7a 架構的 SO 檔案,這樣能獲得更好的效能效果。

總結

以上便是關於 SO 檔案相容適配的一點總結梳理,如有錯誤,歡迎指出。

參考文章

相關文章