1. 程式人生 > >Android中的so庫

Android中的so庫

Android裝置的CPU型別

目前Android裝置已經支援多種CPU型別,包括:

armeabiv-v7a: 第7代及以上的 ARM 處理器。2011年15月以後的生產的大部分Android裝置都使用它.
arm64-v8a: 第8代、64位ARM處理器。
armeabi: 第5代、第6代的ARM處理器,早期的手機用的比較多。
x86: 平板用得比較多。
x86_64: 64位的平板。

其中,arm64-v8a是可以向下相容的,但前提是你的專案裡面沒有arm64-v8a的資料夾,如果你有兩個資料夾armeabi和arm64-v8a,兩個資料夾,armeabi裡面有a.so 和 b.so,arm64-v8a裡面只有a.so,那麼arm64-v8a的手機在用到b的時候發現有arm64-v8a的資料夾,發現裡面沒有b.so,就報錯了,所以這個時候刪掉arm64-v8a資料夾,這個時候手機發現沒有適配arm64-v8a,就會直接去找armeabi的so庫,所以要麼你別加arm64-v8a,要麼armeabi裡面有的so庫,arm64-v8a裡面也必須有。

早期的Android系統幾乎只支援ARMv5的CPU架構,你知道現在它支援多少種嗎?7種!

Android系統目前支援以下七種不同的CPU架構:ARMv5,ARMv7 (從2010年起),x86 (從2011年起),MIPS (從2012年起),ARMv8,MIPS64和x86_64 (從2014年起),每一種都關聯著一個相應的ABI。

應用程式二進位制介面(Application Binary Interface)定義了二進位制檔案(尤其是.so檔案)如何執行在相應的系統平臺上,從使用的指令集,記憶體對齊到可用的系統函式庫。在Android系統上,每一個CPU架構對應一個ABI:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64。

為什麼你需要重點關注.so檔案

如果專案中使用到了NDK,它將會生成.so檔案,因此顯然你已經在關注它了。如果只是使用Java語言進行編碼,你可能在想不需要關注.so檔案了吧,因為Java是跨平臺的。但事實上,即使你在專案中只是使用Java語言,很多情況下,你可能並沒有意識到專案中依賴的函式庫或者引擎庫裡面已經嵌入了.so檔案,並依賴於不同的ABI。

例如,專案中使用RenderScript支援庫,OpenCV,Unity,android-gif-drawable,SQLCipher等,你都已經在生成的APK檔案中包含.so檔案了,而你需要關注.so檔案。

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檔案的話。

App中可能出錯的地方

你應該儘可能的提供專為每個ABI優化過的.so檔案,但要麼全部支援,要麼都不支援:你不應該混合著使用。你應該為每個ABI目錄提供對應的.so檔案。

當一個應用安裝在裝置上,只有該裝置支援的CPU架構對應的.so檔案會被安裝。在x86裝置上,libs/x86目錄中如果存在.so檔案的話,會被安裝,如果不存在,則會選擇armeabi-v7a中的.so檔案,如果也不存在,則選擇armeabi目錄中的.so檔案(因為x86裝置也支援armeabi-v7a和armeabi)。