PrimUpdate
灵活的版本更新库
客户端处理版本更新流程分析
1. 获取APP的相关信息,向服务器发送版本更新请求
2. 如果没有更新 --> 做对应的操作
3. 如果有更新 --> 是强制更新,还是非强制更新
4. 如果是强制更新 --> 用户必须进行更新操作(更新可能包括 全量更新或增量更新)
5. 如果是非强制更新 --> 用户选择进行更新操作 (更新可能包括 全量更新或增量更新)
6. 如果是非强制更新 --> 用户不选择更新操作 --> 是否静默后台下载安装包操作
7. 有安装包提示用户安装
版本更新封装流程分析
- UpdateManager版本更新的管理者:决定事情的方向,管理者只需要知道任务的执行度和完成情况.
- 具体如何实现交给总管去分配和督查所有任务{@link UpdateExplorer} 将任务情况报告给管理者
UpdateExplorer版本更新的总管,分配和督查所有任务: - 以下为任务步骤
- 任务开始 -- 总管得到管理者的决策后开始分配任务
- 任务步骤1 - 检测版本更新 --> 具体实现者:{@link IUpdateChecker}
- 任务步骤2 - 解析json转换为bean --> 具体实现者:{@link IUpdateConverter}
- 任务步骤3 - 对bean进行分析采取方案 --> 具体实现者:{@link IUpdatePlan}
- 任务步骤4 - 版本更新UI提示 --> 具体实现者:{@link IUpdatePrompter}
- 任务步骤5 - 下载apk --> 具体实现者:{@link IUpdateDownloader}
- 任务步骤6 - 下载过程中的UI显示 --> 具体实现者:{@link OnDownloadListener}
- 任务步骤7 - 安装apk --> 具体实现者:{@link IUpdateFile}
- 任务步骤8 - 记录-过程穿插整个任务过程--> 具体实现者:{@link IUpdateLogger}
- 任务完成 -- 由总管向管理者汇报任务情况,并把任务记录传给管理者
- 中间可以插入扩展任务,具体实现看业务需求
灵活
其中每一个任务步骤都可以进行重写、插入、根据业务需求扩展
可扩展的地方:
UpdateConverter 转换数据类,将json字符串转换成bean
public class UpdateConverter implements IUpdateConverter {
/**
* 重要的事情说三遍
* 请自行修改,不同的项目服务器和客户端约定一个数表示成功
* 请自行修改,不同的项目服务器会和客户端约定一个数表示成功
* 请自行修改,不同的项目服务器会和客户端约定一个数表示成功
*/
private String SUCCESS = "0";
private static final String TAG = "UpdateConverter";
@Override
public UpdateInfo convertJson(String info, IUpdateExplorer explorer) throws Throwable {
UpdateState.setState(StateType.CONVERTER);
try {
// 重要的事情说三遍
// json bean 自行修改
// json bean 自行修改
// json bean 自行修改
LzyResponse lzy = GsonUtill.getObejctFromJSON(info, LzyResponse.class);
if (lzy.result.errorCode.equals(SUCCESS)) {
// 重要的事情说三遍
// 如果bean 不一样请注意更换为UpdateInfo bean
// 如果bean 不一样请注意更换为UpdateInfo bean
// 如果bean 不一样请注意更换为UpdateInfo bean
return lzy.data;
} else {
explorer.stop();
return null;
}
} catch (Exception e) {
explorer.stop();
return null;
}
}
}
UpdatePlaner 对解析到的bean 判断采取对应的方案
public class UpdatePlaner implements IUpdatePlan {
private static final String TAG = "UpdatePlaner";
@Override
public void plan(UpdateInfo info, IUpdateExplorer explorer) {
Log.e(TAG, "plan: " + info);
UpdateState.setState(StateType.PLAN);
if (info == null) {
explorer.stop();
return;
}
if (info.isNoUpdate()) {//不需要更新,终止任务
explorer.stop();
} else {//需要更新
//判断用户是否忽略了更新 如果用户忽略了更新不再提示该版本 任务终止
if (SPUtils.getInstance("ignore").getBoolean(info.getVersion_name(), false)) {
if (explorer.getBuilder().isIgnorable) {
explorer.stop();
explorer.showToast("已忽略该版本:" + info.getVersion_name());
return;
} else {
SPUtils.getInstance("ignore").clear();
}
}
//如果用户没有忽略更新
//1 先判断最新的apk包是否存在
//2 存储第一次更新UI提示时间
//3 获取服务器返回的提示周期或者是一天内的提示次数,具体规则根据业务需求定制
if (explorer.isApkCompleteExits()) {// 最新apk存在
/* 用户是否设置了强制重新下载 */
if (explorer.getBuilder().isDownloadAgain) {
FileUtils.deleteFile(explorer.getDownloadPath());
explorer.doPrompter(UpdateExplorer.PrompterType.update);//更新提示
} else {
explorer.doPrompter(UpdateExplorer.PrompterType.install);//安装UI提示
}
} else if (explorer.isAutoDownload()) {// 发现新版本自动下载apk
explorer.doDownload();// 不需要任何UI提示
} else {
serverUpdateTime(info, explorer);
}
}
}
/** 根据更新UI提示的时间 */
private void serverUpdateTime(UpdateInfo info, IUpdateExplorer explorer) {
if (!explorer.getBuilder().isCycleUpdatePrompter) {//没有开启周期UI提示
explorer.doPrompter(UpdateExplorer.PrompterType.update);//更新UI提示
SPUtils.getInstance("Update").clear();
return;
}
String logUpdateTime = SPUtils.getInstance("Update").getString(info.getVersion_name());
if (TextUtils.isEmpty(logUpdateTime)) {// 第一次提示
explorer.doPrompter(UpdateExplorer.PrompterType.update);//更新UI提示
//记录当前提示的时间
SPUtils.getInstance("Update").put(info.getVersion_name(), String.valueOf(System.currentTimeMillis()));
} else {// 第二次提示
if (explorer.getBuilder().prompterPriority) {//true 手动设置的优先级高 以手动设置的时间为准
if (explorer.getBuilder().prompterTime == -1) {//若没有设置手动时间以服务器时间为准
checkTime(info, explorer, logUpdateTime, info.getTime());
} else {//如果设置了手动时间
checkTime(info, explorer, logUpdateTime, explorer.getBuilder().prompterTime);
}
} else {
checkTime(info, explorer, logUpdateTime, info.getTime());
}
}
}
/** 检查时间 */
private void checkTime(UpdateInfo info, IUpdateExplorer explorer, String logUpdateTime, int time) {
if (Utils.getUpdateTime(logUpdateTime, time)) {//已超过设定的提示时间
explorer.doPrompter(UpdateExplorer.PrompterType.update);//更新UI提示
//记录当前提示的时间
SPUtils.getInstance("Update").put(info.getVersion_name(), String.valueOf(System.currentTimeMillis()));
} else {
explorer.showToast("没有超过设定的提示周期:" + time + "天");
explorer.stop();
}
}
}
UI提示的修改:更新提示弹窗、下载提示弹窗等
TODO
继续优化的点:
支持patch更新
网友评论