上月领导有想法,希望公司能实现热更新的技术与提供解决方案,应对一些函数,变量,配置级别的bug的修复。特去整理了下,整理了三个可探究的方案:andfix Dexposed ClassLoader。
现在整理下优缺点:
Dexposed:支持的系统版本,上限是4.4,直接pass,采用的AOP切片式思维,在数据统计这块有大用途,阿里开源的库,比较老的一个库;
ClassLoader: 插件式思维,和注入式更新还是有点不一样;
andfix:支持的系统全面,阿里2015年开源的库,在native层注入代码,解决思路有点类似IOS的jspatch。
最终决定,采用andfix的解决方案,马上教程式的给出集成方案。
一、基础原理
全称Android hot-fix,是alibaba的Android热修复框架,支持Android 2.3到6.0的版本,支持arm与X86系统架构,支持Dalvik和ART Runtime。
原理
AndFix的原理就是方法的替换,把有bug的方法替换成补丁文件中的方法。
原理-替换方法
二、使用教程
1)github上的链接
https://github.com/alibaba/AndFix
作为module集成到项目中
2)在AndroidMainFest.xml中生命所需要的权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
3) 添加依赖和混淆
dependencies { compile 'com.alipay.euler:andfix:0.4.0@aar' }
-keep class * extends java.lang.annotation.Annotation
-keepclasseswithmembernames class * {
native <methods>;
}
4)在Application.onCreate()中初始化PatchManager
public class HotPatchApplication extends Application {
public static PatchManager mPatchManager;
@Override
public void onCreate() {
super.onCreate();
// 初始化patch管理类
mPatchManager = new PatchManager(this);
// 初始化patch版本
mPatchManager.init("1.0");
// 加载已经添加到PatchManager中的patch
mPatchManager.loadPatch();
}
}
5)找个地方加载补丁,我们这里为了演示,点击按钮进行加载补丁
findViewById(R.id.main_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
update();
}
});
private void update() {
String patchFileStr = Environment.getExternalStorageDirectory().getAbsolutePath() + APATCH_PATH;
try {
HotPatchApplication.mPatchManager.addPatch(patchFileStr);
} catch (IOException e) {
e.printStackTrace();
}
}
PatchManager的addPatch方法加载新补丁,项目中可以在下载补丁文件之后调用,这里为了演示就把补丁文件放在本地的SD卡中了,代码中patchFileStr就是补丁存放的位置,.apatch就是生成补丁文件的后缀名,fix就是补丁文件的名字,这里我们将其名字写死。
至此,热更新的功能代码全部写完
6)写上测试是否替代成功的代码
热更新覆盖前的代码如下:
mainTv = (TextView) findViewById(R.id.main_tv);mainTv.setText("点击Toast");
mainTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showToast();
}
});
private void showToast() {
Toast.makeText(this, "打补丁之前", Toast.LENGTH_LONG).show();
}
编译打包城一个old.apk(使用release的签名证书)
热更新覆盖的代码如下:
mainTv = (TextView) findViewById(R.id.main_tv);
mainTv.setText("点击Toast");
mainTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showToast();
}
});
private void showToast() {
Toast.makeText(this, "打补丁之后", Toast.LENGTH_LONG).show();
}
编译打包成一个new.apk(使用release的签名证书)。
三、测试过程
1)
使用andfix中的diff工具执行,生成一个appatch文件,命名为fix.appacth
2)
adb push上述fix.appatch文件到sd卡中;
3)
安装old.apk
4)打开app,点击跟新,
点击更新按钮,然后点击toast按钮,应当能看到 “打补丁之后”的提示。