1.什麼叫熱更新
熱更新是一種各大手遊等衆多App常用的更新方式。簡單來說,就是在使用者通過App Store下載下傳App之後,打開App時遇到的即時更新。
2.為什麼要做熱更新
當一個App釋出之後,突然發現了一個嚴重bug需要進行緊急修複,這時候公司各方就會忙得焦頭爛額:重新打包App、測試、向各個應用市場和管道換包、提示使用者更新、使用者下載下傳、覆寫安裝。
重點是還會有原來的版本遺留,無論你怎麼提示都有人放棄治療,不願意更新,強制不能使用體驗又足夠糟糕到讓人不能啟齒。
如果這是一個影響公司收入或者體驗影響極其不好的Bug,那完蛋了,可能公司老闆會對整個技術團隊的技術能力喪失信心,其對技術人員的傷害是緻命的。
熱更新的方案
技術派系:
• Native,代表有阿裡的Dexposed、AndFix與騰訊的内部方案KKFix;
• Java,代表有Qzone的超級更新檔、大衆點評的nuwa、百度金融的rocooFix, 餓了麼的amigo以及美團的robust。
Native流派與Java流派都有着自己的優缺點,它們具體差異大家可參考上文。事實上從來都沒有最好的方案,隻有最适合自己的。
ClassLoader
我們知道Java在運作時加載對應的類是通過ClassLoader來實作的,ClassLoader本身是一個抽象類,Android中使用PathClassLoader類作為Android的預設的類加載器,
PathClassLoader其實實作的就是簡單的從檔案系統中加載類檔案。PathClassLoade本身繼承自BaseDexClassLoader,BaseDexClassLoader重寫了findClass方法,
該方法是ClassLoader的核心
@Override
protected Class
實作
上面分析了Android中的類的加載的流程,可以看出來DexPathList對象中的dexElements清單是類加載的一個核心,一個類如果能被成功加載,那麼它的dex一定
會出現在dexElements所對應的dex檔案中,并且dexElements中出現的順序也很重要,在dexElements前面出現的dex會被優先加載,一旦Class被加載成功,
就會立即傳回,也就是說,我們的如果想做hotpatch,一定要保證我們的hotpacth dex檔案出現在dexElements清單的前面。
要實作熱更新,就需要我們在運作時去更改PathClassLoader.pathList.dexElements,由于這些屬性都是private的,是以需要通過反射來修改。另外,構造我們自己的dex檔案
所對應的dexElements數組的時候,我們也可以采取一個比較取巧的方式,就是通過構造一個DexClassLoader對象來加載我們的dex檔案,并且調用一次dexClassLoader.loadClass(dummyClassName);
方法,這樣,dexClassLoader.pathList.dexElements中,就會包含我們的dex,通過把dexClassLoader.pathList.dexElements插入到系統預設的classLoader.pathList.dexElements清單前面,就可以讓系統優先加載我們的dex中的類,進而可以實作熱更新了。
說了那麼多,下面我們就以阿裡百川HotFix熱更新內建加使用
首先建立開發者賬号,并建立一個應用如下:參數填入到對應的位置在清單檔案中
1.Androidstutio內建:
首先還是按照阿裡文檔內建,有可能不成功的(文檔上面說了注意: 1.4.0版本的倉庫位址已經發生了變更, 請更新到上述百川最新的倉庫位址),反正我是沒有成功
我的(這是根據阿裡給的dome裡面配置的):
2.先在project的gradle裡面添加:
allprojects {
repositories {
jcenter()
maven {
//百川倉庫, ut/utdid
url “http://repo.baichuan-android.taobao.com/content/groups/BaichuanRepositories”
}
}
}
然後在module的gradle中添加:
dependencies {
compile ‘com.taobao.android:alisdk-hotfix:1.4.0’
}
3.建立一個Application
public class Myapplication extends Application {
@Override
public void onCreate() {
super.onCreate();
HotFixManager.getInstance().setContext(this)
.setAppVersion(“你的版本号”)
.setAppId(“你在開發者平台建立應用的appId”)
.setAesKey(null)//如果對更新檔進行了Aes加密,這裡就要填上,具體見開發文檔
.setSupportHotpatch(true)
.setEnableDebug(true)
.setPatchLoadStatusStub(new PatchLoadStatusListener() {
@Override
public void onload(final int mode, final int code, final String info, final int handlePatchVersion) {
// 更新檔加載回調通知
if (code == PatchStatusCode.CODE_SUCCESS_LOAD) {
// TODO: 10/24/16 表明更新檔加載成功
} else if (code == PatchStatusCode.CODE_ERROR_NEEDRESTART) {
// TODO: 10/24/16 表明新更新檔生效需要重新開機. 業務方可自行實作邏輯, 提示使用者或者強制重新開機, 建議: 使用者可以監聽進入背景事件, 然後應用自殺
} else if (code == PatchStatusCode.CODE_ERROR_INNERENGINEFAIL) {
// 内部引擎加載異常, 推薦此時清空本地更新檔, 但是不清空本地版本号, 防止失敗更新檔重複加載
//HotFixManager.getInstance().cleanPatches(false);
} else {
// TODO: 10/25/16 其它錯誤資訊, 檢視PatchStatusCode類說明
}
}
}).initialize();
}
}
4.添加網絡權限
uses-permission android:name=”android.permission.INTERNET” />
uses-permission android:name=”android.permission.ACCESS_NETWORK_STATE” />
uses-permission android:name=”android.permission.ACCESS_WIFI_STATE” />
uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE”/>
在清單檔案中添加key
至此我們的內建過程就已經完成了,下面進入調試使用階段
首先我們要建立一個old.apk(也就是有問題的apk)
首先将Myapplication中的.setAppVersion(“1.0”)//設定一個版本号,随便設定,後面再上傳更新檔的時候會将更新檔的版本号改成這個,這兩個地方的版本哈要一緻
接下來我們釋出一個有問題的apk或是說old.apk,并将這個old.apk放到一個單獨的地方(我的:C:\Users\Laer\Desktop\oldApk\old.apk),以免釋出新版本的時候覆寫這個舊版本(這個old.apk會在生成更新檔時用到)
然後更改想要修改的代碼,直接釋出生成一個new.apk,同理将這個新的apk放到一個特定的位置(我的: C:\Users\Laer\Desktop\newApk\new.apk)
接下來我們就要使用阿裡提供的生成更新檔的工具了:
http://ams-hotfix-repo.oss-cn-shanghai.aliyuncs.com/SophixPatchTool_windows.zip
下載下傳後解壓,點選SophixPatchTool.exe 可能會出現無響應等一下就好
設定響應的參數
然後點選go,稍等一下,即可生成響應的更新檔:
然後登陸阿裡雲找到對應的移動熱修複進行如下操作即可
這樣一個完整的熱修複就做完了,如有疑問請移步到https://help.aliyun.com/document_detail/53247.html?spm=5176.product51340.6.549.ZMQ9JH