至于AndFix和SoPhix的原理,机制我就不赘言了,网上大把的资料,阿里云上也有非常详细的说明。本文注意介绍集成的步骤
一· AndFix集成
config.gradle
dependencies = [
...
andfix : "com.alipay.euler:andfix:0.5.0@aar"
]
base.gradle
api rootProject.ext.dependencies["andfix"]
MyApplication
public class MyApplication extends BaseApplication {
private RefWatcher refWatcher;
private PatchManager mPatchManager;
@Override
public void onCreate() {
super.onCreate();
refWatcher= setupLeakCanary();
mPatchManager = new PatchManager(this);
mPatchManager.init("1.0");
Log.d("TAG","inited");
mPatchManager.loadPatch();
}
private RefWatcher setupLeakCanary() {
if (LeakCanary.isInAnalyzerProcess(this)) {
return RefWatcher.DISABLED;
}
return LeakCanary.install(this);
}
public static RefWatcher getRefWatcher(Context context) {
MyApplication leakApplication = (MyApplication) context.getApplicationContext();
return leakApplication.refWatcher;
}
}
MainActivity的点击事件中一个弹出Toast的函数作为测试热修复的测试函数
分别是
private void showMsg(){
Toast.makeText(this,"new",Toast.LENGTH_LONG).show();
}
private void showMsg(){
Toast.makeText(this,"old",Toast.LENGTH_LONG).show();
}
接下来就是生成jks签名文件(AndroidStudio)
分别打出新老两个签名包
放在同一个文件夹下面,如图所示
接下来要做的就是下载apkpatch-1.0.3.jar工具包,内不包含了shell和bat脚本
本文是MAC下,采用shell脚本
执行生成补丁包命令:
./apkpatch.sh -f new.apk -t old.apk -k mytest.jks -p 12205226 -a key0 -e 12205226 -o patch
注意:由于命令行中写了new.apk && old.apk,所以请务必将打包出来的包名修改名称,与此同名
大家对比签名文件就知道哪些是参数了
signingConfigs{
config {
keyAlias 'key0'
keyPassword '12205226'
storeFile file('/Users/mac/Desktop/mytest.jks')
storePassword '12205226'
}
}
提供一些apkapatch命令的说明:
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.
命令执行完后会在patch文件生成
如果大家感兴趣呢可以去研究一下android反编译的三个套装 dex2jar工具可以将diff.dex专为 diff.dex.jar可以查看内部源码,会有标签标识出需要修复的函数名称。
主要是看.apatch文件,这个就是补丁包文件 根据代码中加载的名称可以修改.apatch的名称
mv new-86.......0.apatch yourname.apatch
记下来安装old.apk
adb install old.apk
然后push 补丁文件到sd卡上,当然了,也可以通过服务器下载补丁文件
adb push ./out.apatch /sdcard
我的代码中的补丁文件名称定义为out.apatch 名称自行修改
接下来看调用的代码其实也非常简单
private void loadPatch(){
String patchFileString = Environment.getExternalStorageDirectory()
.getAbsolutePath() + APATCH_PATH;
if(new File(patchFileString).exists()){
try {
MyApplication.mPatchManager.addPatch(patchFileString);
} catch (IOException e) {
e.printStackTrace();
}
Log.d("TAG",patchFileString);
}
// File f = new File(this.getFilesDir(), DIR + APATCH_PATH);
// if (f.exists()) {
// boolean result = new File(patchFileString).delete();
// if (!result) {
// Log.e("TAG", patchFileString + " delete fail");
// }
// }
}
APATCH_PATH 的值是 “./out.apatch”
操作步骤 先安装old.apk点击事件show出来的是old 当我们push之后,执行loadPatch方法后,在点击就可以发现弹出的是new了
AndFix的原理上还是有缺陷的,涉及到虚拟机,而虚拟机以Android5.0为分界线有存在差异,特别是后面的厂家都有订制所以对于适配问题是一个非常挑战和头疼的事情,是不是有的小伙伴发现放到sdcard上死活不行,这就是不同的手机文件系统差异性造成的,建议使用网络下载apatch文件在addPatch()。
对于AndFix的兼容性问题。阿里给出了加强版的方案SoPhxi-HotFix方案。