Android 開發 SDK 時應該注意的關於 ABI 的兼容策略
參考
https://www.jianshu.com/p/d2119b3880d8
https://developer.android.google.cn/ndk/guides/abis
ABI
ABI 是 Application binary interface,應用程序二進制接口的縮寫.
不同的 Android 手機使用不同的 CPU,進而支持不同的指令集。 CPU 與指令集的每種組合都有專屬的應用二進制界面,即 ABI。 ABI 可以非常精確地定義應用的機器代碼在運行時如何與系統交互。 您必須為應用要使用的每個 CPU 架構指定 ABI。
ABI 的指定是在代碼的編譯階段進行的,我們使用的各種靜態庫、動態庫,就是支持某個 ABI 的。所以我們在集成很多第三方庫的時候,教程會讓我們把 so 放到指定的文件夾中,文件夾命名其實就是 ABI 的名字。
比如高德地圖:
“使用自定義配置,將下載文件的 armeabi 文件夾復制到 libs 目錄,如果有這個目錄,請將下載的 so 庫復制到這個目錄”
Android 支持的 ABI 如下表:
在 Android Studio 里可以通過下面的配置設置工程支持的 ABI:
ndk {
// 設置支持的SO庫架構
abiFilters 'armeabi-v7a','armeabi', 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
}
主流的ABI架構
- armeabi: 第5代、第6代的ARM處理器,早期的手機用的比較多。
- armeabi-v7a: 第7代及以上的 ARM 處理器。2011年以后的生產的大部分Android設備都使用它。
- arm64-v8a: 第8代、64位ARM處理器,很少設備,三星 Galaxy S6是其中之一。
- x86: 平板、模擬器用得比較多。
- x86_64: 64位的平板。
ABI 兼容策略
正常來講,我們應該為每種 ABI 提供對應的 so 文件,但是實際場景中往往沒有這么做,原因一般有以下幾點:
- 項目體積會比較大。
- 庫的源碼往往不是自己維護的,所以有些庫,沒有某種 ABI 下的文件。(使用了很多 C++ 庫的情況常見)
- 硬件和 Rom 是自己定制的,不需要適配那么多 CPU。(Android 智能設備常見這種情況)
如果我們不能夠為所有架構都提供所有對應的 so,兼容工作就十分重要了。在做 SDK 開發的時候,由於 SDK 支持的 ABI 和 宿主工程支持的 ABI 可能有多種組合,所以尤其要搞明白 ABI 是如何工作的
重要原則:
- CPU 大都像前兼容,比如 ARMv7 的 CPU 除了支持 armeabi-v7a,也支持 armeabi,ARMv8 的 CPU 支持 armeabi,armeabi-v7a,arm64-v8a 三種 ABI。
- 系統優先選擇對應 ABI 文件夾下的 so,比如 ARMv7 的設備,會優先選擇 armeabi-v7a 下的 so 進行加載。如果文件夾存在,且 so 存在,則正常加載;如果了文件夾存在,so不存在,則運行時崩潰;如果文件夾不存在,則會去 armeabi 文件夾下找 so。具體流程用下面流程圖表示:
- 使用了兼容的 so ,雖然一般不會出現 Crash,但是可能有性能損失。
- 對於每個 ABI 下的so,要么全部支持,要不都不支持。
把一些 case 匯總到表格:
可以看到,如果 SDK 支持 armeabi、armeabi-v7a、arm64-v8a 的話,幾乎可以覆蓋全部場景,Android 手機助手也正是采用了表格中的第4行的情形,因為一些庫沒有 armeabi 架構的支持包,所以最終使用了這種方式。