Android SO文件的兼容和適配

原文首發於我的個人博客:blog.coderclock.com/201

開發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文件兼容適配的一點總結梳理,如有錯誤,歡迎指出。

參考文章

關於Android的.so文件你所需要知道的

ABI 管理 | Android Developers

喜歡我的文章,可以關注我的知乎專欄!

我的微信公眾號:技術視界

我的個人博客:blog.coderclock.com/

我的Diycode:diycode.cc/d_clock

我的知乎:D-clock愛吃蔥花 - 知乎

新浪微博:D_clock愛吃蔥花


推薦閱讀:

珍愛生命,遠離蘋果
了解 Android 8.0 中的自動填充
使用 Annotation 改善 Android 代碼
重載Finalize引發的內存泄露
Google 新推出的 Allo 聊天應用,可能要佔領全宇宙了

TAG:Android | Android开发 |