關於So庫需要知道的知識
Android 關於arm64-v8a、armeabi-v7a、armeabi、x86下的so文件兼容問題
Android 中動態加載 so 文件
一種在Native層動態加載SO庫的方案
在Android中使用dlopen加載so庫
Android Studio如何把so庫編譯進apk中
一、什麼是CPU架構以及ABI
ABI(Application Binary Interface)應用程序二進制接口。
定義了二進制文件(SO庫)如何運行在相應的CPU架構上。
從使用的指令集、內存對齊到可用的系統函數庫。
Android系統目前支持以下七種不同的CPU架構:
- ARMv5 ARMv7 x86 MIPS ARMv8 MIP64和x86_64
- 在Android系統上,每一個CPU架構對應一個ABI:armeabi,armeabi-v7a,x86,mips,arm64-v8a,mips64,x86_64。
爲什麼需要重點關注.SO庫
- 如果項目中使用到了NDK,它將會生成.so文件。
- 很多情況下,你的項目會引用到一些So庫。
- 很多設備都支持多於一種的ABI,例如ARM64和x86設備也可以同時運行armeabi-v7a和armeabi的二進制包。
- 但最好是針對特定平臺提供相應平臺的二進制包。
二、SO庫應該放在什麼地方
- Android Studio工程放在main/jniLibs/ABI目錄中(當然也可以通過在build.gradle文件中的設置jniLibs.srcDir屬性自己指定)
Android Studio如何把so庫編譯進apk中.
- 在build.gradle的android裏,加上
- 就會將libs下的ABI的so庫打包到APK中。
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
打包到APK後:
- 最終APK文件中的lib/ABI目錄中
- /lib//lib.so
三、過濾架構
android {
defaultConfig {
ndk {
abiFilters 'armeabi-v7a' //, 'armeabi', 'arm64-v8a', 'x86', 'x86_64', 'mips', 'mips64'
}
}
}
四、System.load(lib)動態加載SO庫
動態加載即我們不將所需 so 庫直接拷貝到 apk 包裏面。
而是將so庫放到雲端。
先判斷用戶的手機 CPU 架構,再通過某種策略選擇合適的時間去雲端下載該用戶手機最優 ABI 架構的 so 庫文件到本地。
再需要使用通過System.load(lib)動態加載SO庫。
好處:
- 降低了APK包的大小;
- 動態更新 so 庫,比如我們給 so 一個版本號來控制 so 的更新工作;
- 可以更大粒度的實現兼容,不僅僅只針對 ABI 類型,還可以針對 SDK 版本,手機上下文等加載定製版 so 庫
五、Native層加載so庫
爲什麼需要Native加載呢?
- Native層代碼膨脹,通過SO庫來劃分模塊。
- 簡化Java層和C++層的通信。
Native層的so庫動態加載的實現?
- 本質上和C++動態加載DLL是一致的。
- 先調用dlopen()函數,這個函數所需的參數,一個是so庫的路徑,一個是加載模式。
- 在上一步得到so庫句柄之後,這時就可以調用dlsym()函數,傳入so庫句柄和所需的函數或變量名稱,返回相應的函數指針或變量指針
- so庫的調用結束,調用dlclose()函數關閉卸載so庫;
- 如果在打開關閉so庫,或者獲取so庫裏操作對象的指針出現錯誤的時候,可以調用dlerror()函數獲取具體的錯誤原因。