問(wèn)題描述
當(dāng)需要引用 so 庫(kù)的時(shí)候盆顾,正常情況下我們只需要將不同版本的 so 文件分別放置。但是這樣就會(huì)遇到兩個(gè)問(wèn)題:
- 如果每個(gè)架構(gòu)的 so 庫(kù)都放進(jìn)去嘲玫,會(huì)大大增加 apk 包的大小
- 如果偏偏沒(méi)有 arm-v7a 的版本呢僧鲁?是刪除 armeabi-v7a 目錄只保留 armeabi ?還是說(shuō)兩個(gè)目錄下 so 文件數(shù)不同也沒(méi)有關(guān)系牧氮?
首先了解一下 so 文件的類(lèi)型
so 文件的類(lèi)型
在 Android 系統(tǒng)中 ndk 默認(rèn)會(huì)生成如下 7 種 .so琼腔。
- armeabi ARM:v5 第5代、第6代的ARM處理器踱葛,早期的手機(jī)用的比較多丹莲。缺少對(duì)浮點(diǎn)數(shù)計(jì)算的硬件支持,在需要大量計(jì)算時(shí)有性能瓶頸
- armeabi-v7a:v7 目前主流版本尸诽,2011年15月以后的生產(chǎn)的大部分Android設(shè)備都使用它
- arm64-v8a:第8代甥材、64位ARM處理器,很少設(shè)備性含,三星 Galaxy S6是其中之一
- x86:平板洲赵、模擬器用得比較多
- x86_64:x86架構(gòu)的64位。
- mips:極少用于手機(jī)
- mips64:mips架構(gòu)的64位
首先mips和mips64極少用于手機(jī)商蕴,因此可以忽略叠萍;x86和x86_64的架構(gòu)都會(huì)包含由 Intel 提供的稱(chēng)為 Houdini 的指令集動(dòng)態(tài)轉(zhuǎn)碼工具,實(shí)現(xiàn) 對(duì) arm 的兼容究恤,再考慮 x86 1% 以下的市場(chǎng)占有率俭令,x86 相關(guān)的兩個(gè) so 也是可以忽略的;arm64-v8a 是可以向下兼容的部宿,因此也是可以忽略的抄腔。
也就是說(shuō),項(xiàng)目中只需要保存兩種架構(gòu)即可:armeabi 和 armeabi-v7a理张。
android加載 so 庫(kù)的模式
比如當(dāng)前用戶(hù)的手機(jī)是 armeabi-v7a 的赫蛇,apk的armeabi包下有 a.so 和 b.so 兩個(gè)庫(kù),而 armeabi-v7a 包下只有 a.so 一個(gè)庫(kù)雾叭。
- android4.4 的so文件拷貝邏輯
android在掃描apk文件的時(shí)候悟耘,并沒(méi)有保證 zip entry 的掃描順序。加載 libs/<abi>/libxxx.so 時(shí)织狐,首先判斷這個(gè) so 庫(kù)是否是當(dāng)前CPU的架構(gòu)暂幼,如果是的話筏勒,則將一個(gè)類(lèi)似名為 hasPrimary 的 boolean 值置為 true ,然后將 so 庫(kù)拷貝到手機(jī)上旺嬉;如果不是的話管行,則判斷是否已經(jīng)加載過(guò)當(dāng)前CPU架構(gòu)的 so 庫(kù)了,即判斷 hasPrimary 的值邪媳,只有 hasPrimary 的值為 false 時(shí)捐顷,即還沒(méi)有加載過(guò)當(dāng)前CPU架構(gòu)的 so 庫(kù),則將這個(gè) so 庫(kù)拷貝到手機(jī)上雨效。
- 如果首先掃描到 armeabi 包下的 a.so 庫(kù)迅涮,此時(shí)因?yàn)?hasPrimary 默認(rèn)為false,因此會(huì)將 a.so 庫(kù)拷貝到手機(jī)上徽龟,隨后 armeabi 下的 b.so 庫(kù)也會(huì)被拷貝到手機(jī)上
- 如果首先掃描到 armeabi-v7a 包下的 a.so 庫(kù)叮姑,此時(shí)會(huì)將 hasPrimary 置為true,并將 a.so 庫(kù)拷貝到手機(jī)上顿肺,因?yàn)?hasPrimary 的值為 true 戏溺,后面也就不會(huì)拷貝 armeabi 包下的 b.so 庫(kù)了
因此有可能只會(huì)拷貝 armeabi-v7a 下的 a.so 庫(kù)到手機(jī)上,當(dāng)執(zhí)行 b.so 中的邏輯時(shí)屠尊,就會(huì)產(chǎn)生 crash
- android5.0+ 的 so 文件拷貝邏輯
不再以文件為粒度匹配,直接拷貝整個(gè)文件夾耕拷。因此只會(huì)將整個(gè) armeabi-v7a 包下的 so 庫(kù)拷貝讼昆,因此當(dāng)執(zhí)行 b.so 中的邏輯時(shí),也會(huì)產(chǎn)生crash
正確的放置方法
- 為了減小 apk 體積骚烧,只保留 armeabi 和 armeabi-v7a 兩個(gè)文件夾浸赫,并保證這兩個(gè)文件夾中 so 數(shù)量一致
- 對(duì)只提供 armeabi 版本的第三方 so,原樣復(fù)制一份到 armeabi-v7a 文件夾