1. 程式人生 > ># 阿里熱更新方案

# 阿里熱更新方案

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裡面新增:

然後在module的gradle中新增:

dependencies {
compile ‘com.taobao.android:alisdk-hotfix:1.4.0’
}

3.建立一個Application

/**
* Created by Laer on 2016/12/20.
*/
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)

接下來我們就要使用阿里提供的生成補丁的工具了:

然後點選go,稍等一下,即可生成響應的補丁:

然後登陸阿里雲找到對應的移動熱修復進行如下操作即可
這裡寫圖片描述

這裡寫圖片描述