AndFix,全稱是Android hot-fix。是阿里開源的一個Android熱補丁框架,允許APP在不重新發版本的情況下修復線上的bug。支持Android 2.3 到 6.0。
andfix的github地址: https://github.com/alibaba/AndFix
AndFix的集成使用請參照demo (AndFix-Demo,A demo about using AndFix 0.5.0) https://github.com/linghu88/hotfix-andfix
一、andfix使用
1. 首先添加依賴
compile 'com.alipay.euler:andfix:0.3.1@aar'
然后在Application.onCreate()中添加以下代碼:
patchManager = new PatchManager(context); //初始化補丁包管理器
patchManager.init(appversion); //版本 String appversion= getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
patchManager.loadPatch(); //加載所有補丁
注意每次appversion變更都會導致所有補丁被刪除,如果appversion沒有改變,則會加載已經保存的所有補丁。
然后在需要的地方調用PatchManager.addPatch()方法加載新補丁,比如可以在下載補丁文件之后調用。
如果你使用混淆,你要保存mapping.txt,這樣的話你在新版本的構建是就可以借助 "-apply mapping” 來使用它了。
混淆需要加入:
-keep class * extends java.lang.annotation.Annotation
-keepclasseswithmembernames class * {
native <methods>;
}
-keep class com.alipay.euler.andfix.** { *; }
2. 打補丁包,首先生成一個apk文件,然后更改代碼,在修復bug后生成另一個apk。
通過AndFix官方提供的補丁包創建工具apkpatch生成一個.apatch格式的補丁文件,需要提供原apk,修復后的apk,以及一個簽名文件。
可以直接使用命令apkpatch查看具體的使用方法。
使用示例:apkpatch -o D:/Patch/ -k debug.keystore -p android -a androiddebugkey -e android f bug-fix.apk t release.apk
usage: apkpatch -f <new> -t <old> -o <output> -k <keystore> -p <***> -a <alias> -e <***>
-a,--alias <alias> keystore entry alias.
-e,--epassword <***> keystore entry password.
-f,--from <loc> new Apk file path.
-k,--keystore <loc> keystore path.
-n,--name <name> patch name.
-o,--out <dir> output dir.
-p,--kpassword <***> keystore password.
-t,--to <loc> old Apk file path.
有時候你的團隊成員可能會fix各自的bug,這個時候就會有不止一個補丁文件.apatch。這種情況下,可以用這個工具merge這些.apatch文件:
usage: apkpatch -m <apatch_path...> -o <output> -k <keystore> -p <***> -a <alias> -e <***>
-a,--alias <alias> keystore entry alias.
-e,--epassword <***> keystore entry password.
-k,--keystore <loc> keystore path.
-m,--merge <loc...> path of .apatch files.
-n,--name <name> patch name.
-o,--out <dir> output dir.
-p,--kpassword <***> keystore password.
3. 通過網絡傳輸或者adb push的方式將apatch文件傳到手機上;
4. 然后運行到patchManager.addPatch(path)的時候就會加載補丁。//path:補丁文件下載到本地的路徑。
加載過的補丁會被保存到data/packagename/files/apatch_opt目錄下,所以下載過來的補丁用過一次就可以刪除了。
注意:每次產生的apatch文件的名字如果是相同的,結果會導致只有第一次的補丁能生效。只有每次名字不同才能加載,log中應該也有提示。
如果使用andfix官方提供的demo的使用步驟:
1. 導入samplesI/AndFixDemo進你的IDE,給AndFixDemo添加AndFix(library project 或者 aar)的依賴。
2. build 工程,保存應用為1.apk,然后將該apk安裝到手機或者模擬器上。
3. 修改com.euler.test.A,作為Fix后的包。
4. build 工程,保存應用為2.apk
5. Use apkpatch tool to make a patch. 使用apkpatch 工具制作一個補丁文件。
6. Rename the patch file to out.apatch, and then copy it to sdcard.重命名補丁文件為out.apatch ,然后將它拷貝到sdcard上。
7. 運行1.apk然后查看log
二、andfix原理:
apkpatch將兩個apk做一次對比,然后找出不同的部分。可以看到生成的apatch了文件,后綴改成zip再解壓開,里面有一個dex文件。通過jadx查看一下源碼,里面就是被修復的代碼所在的類文件,這些更改過的類都加上了一個_CF的后綴,並且變動的方法都被加上了一個叫@MethodReplace的annotation,通過clazz和method指定了需要替換的方法。然后客戶端sdk得到補丁文件后就會根據annotation來尋找需要替換的方法。最后由JNI層完成方法的替換。如果本地保存了多個補丁,那么AndFix會按照補丁生成的時間順序加載補丁。具體是根據.apatch文件中的PATCH.MF的字段Created-Time。
AndFix通過Java的自定義注解來判斷一個方法是否應該被替換,如果可以就會hook該方法並進行替換。AndFix在ART架構上的Native方法是art_replaceMethod 、在X86架構上的Native方法是dalvik_replaceMethod。他們的實現方式是不同的。對於Dalvik,它將改變目標方法的類型為Native同時hook方法的實現至AndFix自己的Native方法,這個方法稱為dalvik_dispatcher,這個方法將會喚醒已經注冊的回調,這就是我們通常說的hooked(掛鈎)。對於ART來說,我們僅僅改變目標方法的屬性來替代它。
三、 安全驗證:
文件的簽名驗證:AndFix對apatch文件簽名做了是否和應用的簽名是同一個的驗證,不是的話就不加載該補丁。
指紋optimize file驗證:為了防止有人替換掉本地保存的補丁文件,所以要驗證MD5碼。SecurityChecker類里面也已經做了驗證處理,但是這個MD5碼是保存在sharedpreference里面,如果手機已經root那么還是可以被訪問的。
四、優缺點:
優點:
1. 不需要重啟APP即可應用補丁,對用戶透明無感知;
2. 能滿足快速修復問題。
缺點:
1. 無法添加新類和新的字段;
2. 需要使用加固前的apk制作補丁,但是補丁文件很容易被反編譯,也就是修改過的類源碼容易泄露。
3. 使用加固平台可能會使熱補丁功能失效(在360加固提了這個問題,未驗證)。如果你使用了,軟件加固比如 Bangcle,為了生成補丁文件,你最好使用為經過加固的apk.使用這些加固,很可能使熱補丁失效。