深入探索Android熱修復(fù)技術(shù)原理這本書主要講解了Android的熱修復(fù)中的熱部署,冷部署以及資源和so庫的修復(fù)技巧。全文主要講Sophix應(yīng)對(duì)以上四個(gè)方面的技術(shù)解析,不管是自家產(chǎn)品還是業(yè)界其他方案的橫縱對(duì)比,Sophix技術(shù)目前都是最優(yōu)的。
創(chuàng)新互聯(lián)公司專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于做網(wǎng)站、成都做網(wǎng)站、陽朔網(wǎng)絡(luò)推廣、重慶小程序開發(fā)公司、陽朔網(wǎng)絡(luò)營銷、陽朔企業(yè)策劃、陽朔品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們最大的嘉獎(jiǎng);創(chuàng)新互聯(lián)公司為所有大學(xué)生創(chuàng)業(yè)者提供陽朔建站搭建服務(wù),24小時(shí)服務(wù)熱線:18982081108,官方網(wǎng)址:www.cdcxhl.com
在事件分發(fā)流中,通過Hook鉤子在事件傳送到終點(diǎn)前截獲并監(jiān)控事件的傳輸,從而處理一些特定干預(yù)事件。
Sophix同時(shí)使用了熱啟動(dòng)的底層替換方案及冷啟動(dòng)的類加載方案,兩個(gè)方案使用的補(bǔ)丁是相同的。優(yōu)先熱啟動(dòng)。
基本參考InstantRun的實(shí)現(xiàn):構(gòu)造一個(gè)包含所有新資源的新的AssetManager。并在所有之前引用到原來的AssetManager通過反射替換掉。
Sophix不修改AssetManager的引用,構(gòu)造的補(bǔ)丁包中只包含有新增或有修改變動(dòng)的資源,在原AssetManager中addAssetPath這個(gè)包就可以了。資源包不需要在運(yùn)行時(shí)合成完整包。
本質(zhì)是對(duì)native方法的修復(fù)和替換。類似類修復(fù)反射注入方式,將補(bǔ)丁so庫的路徑插入到nativeLibraryDirectories數(shù)據(jù)最前面。
因?yàn)閷?duì)手機(jī)傷害大。android手機(jī)熱修復(fù)不能百分百用戶修復(fù)成功,手機(jī)影響極大而且手機(jī)很容易出現(xiàn)bug,所以手機(jī)廠商不允許熱修復(fù)。
注意:在5.0之前會(huì)有這個(gè)問題,5.0之后沒有了
我們進(jìn)行插樁的時(shí)機(jī),便是上圖中javac之后,dx之前。 另外,任何一個(gè)Task,都有input元素和output元素,以及可以設(shè)置doFirst閉包,表示執(zhí)行任務(wù)之前先執(zhí)行一段邏輯,設(shè)置doLast,表示執(zhí)行任務(wù)執(zhí)行之后再執(zhí)行一段邏輯。
我們的思路是 在java變成class之后,在class變成 dex之前,將class進(jìn)行ASM插樁。所以,我們要找的 gradle task 是 : transformClassesWithDexBuilderForRelease 或者 transformClassesWithDexBuilderForDebug 給它重寫doFirst。 也可以 找到 gradle task : compileReleaseJavaWithJavac 或者 compileDebugJavaWithJavac. 給它重寫 doLast。效果相同。
jar文件的插樁:
本文是在Android8.1.0上進(jìn)行的源碼分析,首先明確幾個(gè)classloader的定義。
dexFile相當(dāng)于一個(gè)classes.dex,而每一個(gè)dexFile也是一個(gè)Element,熱修復(fù)的補(bǔ)丁包一定要插到classes.dex中的最前面的一個(gè)dex開始查找,因?yàn)閐exFile是從classes.dex classes2.dex依次向后進(jìn)行查找的.前面如果找到就不會(huì)找后面的類了。
反射工具類:
熱修復(fù):
成功使用:
最近研究了一下騰訊的熱更新框架,以及一位大神開源的熱更新后臺(tái)服務(wù)框架,下邊總結(jié)一下,希望對(duì)想了解的人有所幫助
tinker鏈接:
開源的熱更新后臺(tái)服務(wù)框架:
一、Tinker使用介紹:
官方文檔好久沒更新了,看起來費(fèi)事,這里簡單總結(jié)下怎么使用。
1、導(dǎo)入Sample工程
將官方給出的 Sample工程 在AndroidStudio中打開.首先一點(diǎn),在app的build.gradle文件中找到tinkerId = getTinkerIdValue()并將其替換成tinkerId = "tinkerId",其中后面的值可以隨意設(shè)置.再替換ignoreWarning = false為ignoreWarning = true.
2、編譯運(yùn)行原版apk
按照往常操作一樣,編譯打包debug apk并安裝.此時(shí)Tinker會(huì)在工程的app/build/bakApk/目錄下保存打包好的apk文件,找到剛才生成的apk文件,復(fù)制其完整文件名,在app的build.gradle文件找到tinkerOldApkPath這一項(xiàng)設(shè)置,并將其設(shè)置為tinkerOldApkPath = "${bakPath}/剛才生成的apk文件名"
3、修改源碼 生成新版apk 補(bǔ)丁
在項(xiàng)目里隨便改點(diǎn)內(nèi)容,然后生成debug版的patch(補(bǔ)丁)apk文件。如圖:
4、生成補(bǔ)丁包的位置如圖:
只需將此補(bǔ)丁包放在MainActivity里邊指定的加載補(bǔ)丁包的路徑即可。
點(diǎn)擊LOAD_PACH 加載執(zhí)行修復(fù),點(diǎn)擊shouInfo 會(huì)顯示PATCH is loaded,說明成功,然后點(diǎn)擊KILL SELF 再次進(jìn)入 就修復(fù)了。
到此為止tinker修復(fù)就成功了。然后說說怎么接入 tinker-manager 手機(jī)端的,以便跟熱更新后臺(tái)的修復(fù)做對(duì)接。
步驟參考文檔鏈接: ?按照此文檔接入就行,我在這里對(duì)參數(shù)進(jìn)行一下說明
下邊兩參數(shù)做測(cè)試的話為空即可
針對(duì)Android平臺(tái),Dexposed支持函數(shù)級(jí)別的在線熱更新,例如對(duì)已經(jīng)發(fā)布在應(yīng)用市場上的宿主APK,當(dāng)我們從crash統(tǒng)計(jì)平臺(tái)上發(fā)現(xiàn)某個(gè)函數(shù)調(diào)用有bug,導(dǎo)致經(jīng)常性crash,這時(shí),可以在本地開發(fā)一個(gè)補(bǔ)丁APK,并發(fā)布到服務(wù)器中,宿主APK下載這個(gè)補(bǔ)丁APK并集成后,就可以很容易修復(fù)這個(gè)crash。
Dexposed是基于久負(fù)盛名的開源Xposed框架實(shí)現(xiàn)的一個(gè)Android平臺(tái)上功能強(qiáng)大的無侵入式運(yùn)行時(shí)AOP框架。
Dexposed的AOP實(shí)現(xiàn)是完全非侵入式的,沒有使用任何注解處理器,編織器或者字節(jié)碼重寫器。集成Dexposed框架很簡單,只需要在應(yīng)用初始化階段加載一個(gè)很小的JNI庫就可以,這個(gè)加載操作已經(jīng)封裝在DexposedBridge函數(shù)庫里面的canDexposed函數(shù)中,源碼如下所示:
/**
* Check device if can run dexposed, and load libs auto.
*/
public synchronized static boolean canDexposed(Context context) {
if (!DeviceCheck.isDeviceSupport(context)) {
return false;
}
//load xposed lib for hook.
return loadDexposedLib(context);
}
private static boolean loadDexposedLib(Context context) {
// load xposed lib for hook.
try {
if (android.os.Build.VERSION.SDK_INT 19){
System.loadLibrary("dexposed_l");
} else if (android.os.Build.VERSION.SDK_INT == 10
|| android.os.Build.VERSION.SDK_INT == 9 ||
android.os.Build.VERSION.SDK_INT 14){
System.loadLibrary("dexposed");
}
return true;
} catch (Throwable e) {
return false;
}
}
Dexposed實(shí)現(xiàn)的hooking,不僅可以hook應(yīng)用中的自定義函數(shù),也可以hook應(yīng)用中調(diào)用的Android框架的函數(shù)。Android開發(fā)者將從這一點(diǎn)得到很多好處,因?yàn)槲覀儑?yán)重依賴于Android SDK的版本碎片化。