美文网首页程序员
灵活的版本更新库封装

灵活的版本更新库封装

作者: 289346a467da | 来源:发表于2018-03-08 19:13 被阅读65次

    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更新

    代码地址:https://github.com/JakePrim/VersionUpdate

    相关文章

      网友评论

        本文标题:灵活的版本更新库封装

        本文链接:https://www.haomeiwen.com/subject/mxayfftx.html