今天我新开了一个专题,说说热更新和插件化。内容这里注明一下,来自慕课网qndroid老师的热更新插件化课程。不过可能老师考虑课已经过时了,所以下架了。我是之前买的,最近刚开始听。写的有问题的地方大家可以指出来,互相学习。老师讲了很多原理,听着很有帮助,但是我的博客一向是希望大家用的时候可以拿来主义。所以原理的东西我不写了,只记录老师讲述的工作中开发可以用到的部分。
今天我说一下AndFix的使用。AndFix是阿里早期推出的一款热更新框架,标明的是Android2.3到Android7.0可以使用。按道理已经废弃了,不过我之所以还要说这个,一方面我开发中发现一些特殊设备的Android版本还在6.0徘徊;另一方面也算从简单到复杂学习过程。
好了,废话不多说了,上代码。
首先是权限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
同样的,一会儿代码中动态权限也要申请。大家根据自己项目的情况进行申请即可。
导入依赖
compile 'com.alipay.euler:andfix:0.5.0@aar'
接着我们创建一个类AndFixPatchManager,这个就是封装好的AndFix热更新类。
代码如下:
public class AndFixPatchManager {
private static AndFixPatchManager mInstance = null;
private static PatchManager mPatchManager = null;
private AndFixPatchManager() {
}
public static AndFixPatchManager getInstance() {
if (mInstance == null) {
synchronized (AndFixPatchManager.class) {
if (mInstance == null) {
mInstance = new AndFixPatchManager();
}
}
}
return mInstance;
}
/**
* 初始化AndFix
*
* @param context
*/
public void initPatch(Context context) {
mPatchManager = new PatchManager(context);
mPatchManager.init(getVersionName(context));
mPatchManager.loadPatch();
}
/**
* 获取版本名称
*
* @param context
* @return
*/
private String getVersionName(Context context) {
String versionName = "1.0.0";
try {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageInfo(context.getPackageName(), 0);
versionName = pi.versionName;
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
return versionName;
}
/**
* 加载补丁
*/
public void addPatch(String path) {
try {
if (mPatchManager != null) {
mPatchManager.addPatch(path);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
在Application中我们调用如下语句
AndFixPatchManager.getInstance().initPatch(this);
这样我们就对AndFix进行初始化了。
这里我们就要说一下了,之前的步骤都是固定的,我们添加权限,集成三方库,封装热更新类,并且在Application中初始化AndFix。之后开始我们要执行以下几步:
1.首先我们有两个版本号,一个是完全版本号,由app自带;一个是热更新版本号,由程序写入sp中。
2.sp中有两个字段。一个是保存的完全版本号,一个是热更新的版本号。每次进入app都要进行判断,如果获取的完全版本号和保存的完全版本号不一致,就要把完全版本号在sp的这两个字段都要保存一遍;如果一致,则不进行此操作。
3.接着app中要进行热更新版本的接口请求,参数要把sp中的热更新版本提上去。服务器返回该版本之后的所有热更新补丁地址。我们逐个下载后进行补丁加载操作。如果操作成功,更新sp中的热更新版本,并删除补丁文件;如果更新失败,删除补丁文件,并请求完全版本的更新。
按照这个步骤,即使我们补丁加载失败了,或者多个补丁叠加加载失败,我们仍然可以进行完全安装进行版本的更新操作。这套更新逻辑可以用在Tinker和Sophix的更新上。另外,热更新的接口上还可以加入这次是否是热更新,如果该版本不能热更新则不给补丁地址,直接进行完全版本更新。
private void loadPatch(String path){
AndFixPatchManager.getInstance().addPatch(path);
}
如果能够正常执行,此时我们的bug就被修复好了,并且实测中无须重启操作。
生成补丁的命令如下:
apkpatch -f new.apk -t old.apk -o outputs/ -k 签名文件 -p kpassword -a alias -e epassword
工具我上传到了我的资源,大家也可以从github上下载。