1鹊汛、前言
前段時間在微信的一個公眾號看到了一篇文章
阿里震撼業(yè)界—推出首個非侵入式熱修復(fù)方案Sophix旷痕,顛覆移動端傳統(tǒng)發(fā)版更新流程亚兄!
對此非常感興趣下翎,因?yàn)橐恢币詠碜约阂蚕胍陧?xiàng)目中加入熱更新的功能缤言,曾經(jīng)試過了微信的Tinker,Gradle配置起來也有點(diǎn)點(diǎn)麻煩漏设,構(gòu)建的過程時間也比較長墨闲,當(dāng)時項(xiàng)目比較趕,也就沒有繼續(xù)往下實(shí)踐了郑口。
看到了阿里的Sophix方案引入確實(shí)比較方便鸳碧,簡單到只需要兩句代碼,當(dāng)然犬性,實(shí)踐起來還是有很多需要注意的地方瞻离,如有不慎,恐怕會引起崩潰乒裆。
阿里云移動熱修復(fù)Sophix官網(wǎng):https://www.aliyun.com/product/hotfix
2套利、非侵入性(原話)
我們的打包過程不會侵入到apk的build流程中。我們所需要的鹤耍,只有已經(jīng)生成完畢的新舊apk肉迫,而至于apk是如何生成的——是Android Studio打包出來的、還是Eclipse打包出來的稿黄、或者是自定義的打包流程喊衫,我們一律不關(guān)心。在生成補(bǔ)丁的過程中間既不會改變?nèi)魏未虬M件杆怕,也不插入任何AOP代碼族购,我們極力做到了——不添加任何超出開發(fā)者預(yù)期的代碼,以避免多余的熱修復(fù)代碼給開發(fā)者帶來困擾陵珍。
3寝杖、實(shí)踐中的一些問題
接入步驟可查看官方文檔,比較簡單互纯,下面是寫入Application的兩句代碼
// initialize最好放在attachBaseContext最前面
SophixManager.getInstance().setContext(this)
.setAppVersion(appVersion)
.setAesKey(null)
.setEnableDebug(true)
.setPatchLoadStatusStub(new PatchLoadStatusListener() {
@Override
public void onLoad(final int mode, final int code, final String info, final int handlePatchVersion) {
// 補(bǔ)丁加載回調(diào)通知
if (code == PatchStatus.CODE_LOAD_SUCCESS) {
// 表明補(bǔ)丁加載成功
} else if (code == PatchStatus.CODE_LOAD_RELAUNCH) {
// 表明新補(bǔ)丁生效需要重啟. 開發(fā)者可提示用戶或者強(qiáng)制重啟;
// 建議: 用戶可以監(jiān)聽進(jìn)入后臺事件, 然后應(yīng)用自殺
} else if (code == PatchStatus.CODE_LOAD_FAIL) {
// 內(nèi)部引擎異常, 推薦此時清空本地補(bǔ)丁, 防止失敗補(bǔ)丁重復(fù)加載
// SophixManager.getInstance().cleanPatches();
} else {
// 其它錯誤信息, 查看PatchStatus類說明
}
}
}).initialize();
// queryAndLoadNewPatch不可放在attachBaseContext 中瑟幕,否則無網(wǎng)絡(luò)權(quán)限,建議放在后面任意時刻,如onCreate中
SophixManager.getInstance().queryAndLoadNewPatch();
3.1收苏、多次補(bǔ)丁的情況亿卤,基線包需要多次修復(fù)補(bǔ)丁
已經(jīng)修復(fù)了V.1版本,當(dāng)需要更新V.2版本的補(bǔ)丁鹿霸,應(yīng)該是以哪個為基線包?應(yīng)該是使用哪個補(bǔ)陡讶椤懦鼠?這里V版本是基線包,patch3是補(bǔ)丁屹堰。
3.2肛冶、項(xiàng)目在Android4.4版本會遇到崩潰現(xiàn)象,應(yīng)該如何避免扯键?
Sophix的初始化代碼要在Application的最前面睦袖,而且盡量使用系統(tǒng)的類,不要使用log等荣刑,最好就是什么代碼都不寫馅笙,回調(diào)方法也不寫代碼,確保不會發(fā)生崩潰現(xiàn)象厉亏。Sophix在修復(fù)的時候回整包dex修復(fù)董习,如果有其他代碼可能會影響到修復(fù)過程。
3.3爱只、Android5.0多dex分包的處理
實(shí)踐的過程中遇到皿淋,項(xiàng)目方法數(shù)大于64k,已經(jīng)采用dex分包技術(shù)恬试,最小支持的API版本如果大于21窝趣,即Android5.0的時候,編譯出來的apk包解壓后可能會有好幾十個dex分包(如下圖所示训柴,正常來說應(yīng)該是1哑舒、2個),該問題會導(dǎo)致在差分包打補(bǔ)丁的時候會出錯畦粮,因此只需要修改最小支持的API版本在5.0以下即可散址。
3.4、項(xiàng)目使用360加固宣赔,能否支持预麸?
測試過了,是支持的儒将。但我個人的測試范圍比較小吏祸,在阿里釘釘群里面有人反映,360加固后會出現(xiàn)崩潰現(xiàn)象钩蚊,且再也無法啟動贡翘,只能卸載重裝蹈矮。這里我沒遇到過,但官方客服并沒有說支持鸣驱,也就是說泛鸟,出現(xiàn)問題并不會快速響應(yīng)幫忙解決。
3.5踊东、采用代碼混淆 + 不加固的方式來發(fā)布應(yīng)用北滥,對于混淆文件mapping.txt的處理
應(yīng)用在上線打包APK時,往往會進(jìn)行混淆操作闸翅,但是由于修復(fù)前后兩個APK混淆結(jié)果不同會導(dǎo)致patch無效再芋,無法修復(fù)bug。所以坚冀,需要注意的是:應(yīng)用打包APK的時候修復(fù)前后兩個APK必須使用同一份mapping.txt济赎,以保證兩個APK混淆結(jié)果一致。
如果app應(yīng)用了混淆配置记某,那么需要做如下處理司训。打包之前,將mapping.txt文件移動到了當(dāng)前模塊的目錄下辙纬,再將混淆文件proguard-rules.pro進(jìn)行如下操作豁遭。
#基線包使用,生成mapping.txt
-printmapping mapping.txt
#生成的mapping.txt在app/buidl/outputs/mapping/release路徑下贺拣,移動到/app路徑下
#修復(fù)后的項(xiàng)目使用蓖谢,保證混淆結(jié)果一致
#-applymapping mapping.txt
#hotfix
-keep class com.taobao.sophix.**{*;}
-keep class com.ta.utdid2.device.**{*;}
#防止inline
-dontoptimize
3.6、項(xiàng)目中多版本譬涡、Debug闪幽、Release版本的熱修復(fù)控制
建議不需要熱更新的版本在
initialize()
queryAndLoadNewPatch()
方法之前加入判斷,不然會報錯涡匀。
3.7盯腌、對比騰訊微信Tinker熱修復(fù)方案
騰訊微信Tinker方案也非常強(qiáng)大,也有一個完善的補(bǔ)丁后臺管理陨瘩,不需要我們的后臺接入就能夠輕松實(shí)現(xiàn)熱修復(fù)的功能腕够。
但有個問題,Tinker需要在Gradle配置里面做比較多的配置腳本舌劳,導(dǎo)致編譯的時候也會非常占用時間帚湘,接入成本相對Sophix來說更大一些。
3.8甚淡、更多問題
官方FQ Android接入問題