AndFix
全稱Android hot-fix,是alibaba的Android熱修復(fù)框架,支持Android 2.3到6.0的版本,支持arm與X86系統(tǒng)架構(gòu),支持Dalvik和ART Runtime。
原理
AndFix的原理就是方法的替換,把有bug的方法替換成補(bǔ)丁文件中的方法。

原理-替換方法.png
使用教程
1. 添加依賴和混淆
compile 'com.alipay.euler:andfix:0.4.0@aar'
}```
**混淆:**
-keep class * extends java.lang.annotation.Annotation
-keepclasseswithmembernames class * {
native <methods>;
}
**2. 在Application.onCreate()中初始化PatchManager**
public class AndFixApplication extends Application {
public static PatchManager mPatchManager;
@Override
public void onCreate() {
super.onCreate();
// 初始化patch管理類
mPatchManager = new PatchManager(this);
// 初始化patch版本
mPatchManager.init("1.0");
// String appVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
// mPatchManager.init(appVersion);
// 加載已經(jīng)添加到PatchManager中的patch
mPatchManager.loadPatch();
}
}
**3. 找個(gè)地方加載補(bǔ)丁,我們這里為了演示,點(diǎn)擊按鈕進(jìn)行加載補(bǔ)丁**
findViewById(R.id.main_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
update();
}
});
private static final String APATCH_PATH = "/fix.apatch"; // 補(bǔ)丁文件名
private void update() {
String patchFileStr = Environment.getExternalStorageDirectory().getAbsolutePath() + APATCH_PATH;
try {
AndFixApplication.mPatchManager.addPatch(patchFileStr);
} catch (IOException e) {
e.printStackTrace();
}
}
PatchManager的addPatch方法加載新補(bǔ)丁,項(xiàng)目中可以在下載補(bǔ)丁文件之后調(diào)用,這里為了演示就把補(bǔ)丁文件放在本地的SD卡中了,代碼中patchFileStr就是補(bǔ)丁存放的位置,**.apatch**就是生成補(bǔ)丁文件的后綴名,fix就是補(bǔ)丁文件的名字,這里我們將其名字寫死。
我們看一下打補(bǔ)丁之前MainActivity的所有代碼
public class MainActivity extends AppCompatActivity {
private static final String APATCH_PATH = "/fix.apatch"; // 補(bǔ)丁文件名
private TextView mainTv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainTv = (TextView) findViewById(R.id.main_tv);
mainTv.setText("點(diǎn)擊Toast");
mainTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showToast();
}
});
findViewById(R.id.main_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
update();
}
});
}
private void showToast() {
Toast.makeText(this, "打補(bǔ)丁之前", Toast.LENGTH_LONG).show();
}
/**
* 動(dòng)態(tài)更新,加載補(bǔ)丁文件
* @author zehua_chen
* create at 2016/8/3 14:35
*/
private void update() {
String patchFileStr = Environment.getExternalStorageDirectory().getAbsolutePath() + APATCH_PATH;
try {
AndFixApplication.mPatchManager.addPatch(patchFileStr);
} catch (IOException e) {
e.printStackTrace();
}
}
}
**4. 我們將以上應(yīng)用打包,我們命名為andfix_v1.0**

**5. 修改MainActivity中的代碼,打包成andfix_v2.0**
private void showToast() {
Toast.makeText(this, "打補(bǔ)丁之后", Toast.LENGTH_LONG).show();
}
mainTv.setText("加載了補(bǔ)丁之后");
上面代碼可知,我們只修改TextView的文字和TextView點(diǎn)擊之后的Toast內(nèi)容,然后打包

**6. 使用官方提供的工具[apkpatch](https://github.com/alibaba/AndFix/blob/master/tools/apkpatch-1.0.3.zip)生成.apatch補(bǔ)丁文件**
點(diǎn)擊上面的鏈接下載apkpatch之后解壓

將兩個(gè)apk文件和該app的簽名文件放入到該目錄中

使用命令生成.apatch補(bǔ)丁文件,先cmd進(jìn)入該目錄

使用命令生成補(bǔ)丁

上圖所示則表示補(bǔ)丁包生成完成
<u>apkpatch.bat -f andfix_v2.0.apk -t andfix_v1.0.apk -o output -k AndFixKey.jks -p andfix -a andfix -e andfix</u>
<u>apkpatch.bat -f 新apk -t 舊apk -o 輸出目錄 -k app簽名文件 -p 簽名文件密碼 -a 簽名文件別名 -e 別名密碼</u>
* -f <new.apk> :新apk
* -t <old.apk> : 舊apk
* -o <output> : 輸出目錄(補(bǔ)丁文件的存放目錄)
* -k <keystore>: 打包所用的keystore
* -p <password>: keystore的密碼
* -a <alias>: keystore 用戶別名
* -e <alias password>: keystore 用戶別名密碼
生成的output文件:


將生成的.apatch補(bǔ)丁文件改成代碼中寫死的fix.apatch

**7.運(yùn)行andfix_v1.0查看修復(fù)之前的效果,把補(bǔ)丁文件push到sd卡目錄下, 點(diǎn)擊Button更新按鈕加載補(bǔ)丁文件,再看其效果,到這里我們就完成了AndFix的熱修復(fù)了**


* 運(yùn)行andfix_v1.0沒(méi)有點(diǎn)擊動(dòng)態(tài)更新按鈕,點(diǎn)擊TextView

* 點(diǎn)擊動(dòng)態(tài)更新Button之后再Toast,我們發(fā)現(xiàn)Tost的內(nèi)容變了,但是TextView的內(nèi)容沒(méi)換

* 退出之后我們重新進(jìn)入該應(yīng)用就會(huì)發(fā)現(xiàn)TextView的內(nèi)容也變化了。
