上次從加載流程介紹了修復(fù)包的加載過程脖咐,還剩下具體的dex
铺敌、res
、libriry
的具體合成和應(yīng)用屁擅。下面我將分別展開介紹:
一偿凭、dex的合成與加載
DexDiffPatchInternal
的方法tryRecoverDexFiles(Tinker manager, ShareSecurityCheck checker, Context context, String patchVersionDirectory, File patchFile, boolean isUpgradePatch)
- 里面有從
ShareSecurityCheck
中得到"assets/dex_meta.txt"
這個(gè)dex修復(fù)包配置文件。 - 然后調(diào)用了
patchDexExtractViaDexDiff(Context context, String patchVersionDirectory, String meta, File patchFile, boolean isUpgradePatch)
這個(gè)方法派歌。
這個(gè)方法是具體的操作:
- 判斷系統(tǒng)版本是art還是dalvik
- 調(diào)用
extractDexDiffInternals(Context context, String dir, String meta, File patchFile, int type, boolean isUpgradePatch)
執(zhí)行diff操作弯囊。 - 生成優(yōu)化dex的目錄,調(diào)用
loadDex(String sourcePathName, String outputPathName, int flags)
加載生成的dex文件硝皂。 - 如果優(yōu)化失敗常挚,則刪除文件,并報(bào)告錯(cuò)誤稽物。
下面步步推進(jìn)奄毡,再介紹上一個(gè)方法里面的核心方法:extractDexDiffInternals(Context context, String dir, String meta, File patchFile, int type, boolean isUpgradePatch)
- 從
dex_meta.txt
中得到各個(gè)dex的配置信息ArrayList<ShareDexDiffPatchInfo> patchList
- 得到兩個(gè)
ZipFile
:應(yīng)用本身的和修復(fù)包的。 - 在art系統(tǒng)中得到修復(fù)包中的小的dex文件
SmallPatchedDexItemFile
- for循環(huán)
patchList
里面包含了md5值(dalvik
和art
不同)贝或,dex文件的路徑等信息吼过。若文件存在并且md5相同,則continue咪奖,不再處理盗忱。
這里面有幾個(gè)文件需要區(qū)別一下,有點(diǎn)繞:
1.dir
或者patchVersionDirectory
是安全目錄羊赵,而patchFile
不是安全目錄趟佃。
2.extractFile
是安全目錄下的真名字扇谣,比如class.dex
。
3.patchRealPath
是從dex_meta.txt
文件中取到的真實(shí)class.dex
路徑闲昭。
4.分別得到apk
和patch
包中dex
文件的ZipEntry
ZipEntry patchFileEntry = patch.getEntry(patchRealPath);
ZipEntry rawApkFileEntry = apk.getEntry(patchRealPath);
最終調(diào)用這個(gè)方法罐寨,完成合成的操作。
new DexPatchApplier(oldInputStream, oldDexSize, newInputStream,
smallPatchInfoFile).executeAndSaveTo(zos);
里面對(duì)dex文件分?jǐn)?shù)據(jù)類型進(jìn)行對(duì)比序矩,合成鸯绿。(dexdiff)
二、TinkerInstall的調(diào)用時(shí)機(jī)
有兩個(gè)作用:
1.回調(diào)LoaderReporter
簸淀,返回加載結(jié)果瓶蝴。
2.初始化各個(gè)自定義類與Tinker
實(shí)例,可以通過Tinker
來調(diào)用相關(guān)api
租幕。發(fā)起升級(jí)補(bǔ)丁以及處理相關(guān)回調(diào)舷手。
即使不調(diào)用也不影響Tinker
對(duì)資源,dex
令蛉,libriry
的加載聚霜。