AppUpdate分析

背景

最近小组里需要替换升级模块,自己在GitHub上找到了一个挺不错的开源第三方库,AppUpdate感觉写得挺不错的,使用文档也说得挺详细,下面就对这个框架进行一下调用分析。

接口设计

检查是否有新版本接口

  • 接口URL
mCheckUpdateUrl = mHostUrl + "/app/checkUpdate.do";
  • 发送的数据
{
    "appKey" :
    // appKey是预先写在App的AndroidMenifest.xml文件中的
    // 在发送请求的时候,后台进行这个appKey的判断,如果值不对,就不返回下载的信息了。
    // 这个值事先需要跟后台协商好。
    "ab55ce55Ac4bcP408cPb8c1Aaeac179c5f6f",
    "version" : "1.0.2732"
}
  • 返回的数据
{
    "update": "Yes",
    "new_version": "0.8.3",
    "apk_file_url": "https://raw.githubusercontent.com/WVector/AppUpdateDemo/master/apk/app-debug.apk",
    "update_log": "1,添加删除信用卡接口。\r\n2,添加vip认证。\r\n3,区分自定义消费,一个小时不限制。\r\n4,添加放弃任务接口,小时内不生成。\r\n5,消费任务手动生成。",
    "target_size": "5M",
    "new_md5":"295687E756F569C7159974DD493489A5",
    "constraint": false
}

后台数据库sql脚本

-- ----------------------------
--  Table structure for `app_update`
-- ----------------------------
DROP TABLE IF EXISTS `app_update`;
CREATE TABLE `app_update` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `update` int(11) DEFAULT '1' COMMENT '是否启动更新,返回给客户端的时候,转成true',
  `new_version` varchar(35) DEFAULT NULL COMMENT '最新版本号',
  `apk_file_url` varchar(500) DEFAULT NULL COMMENT 'apk的下载路径',
  `update_log` varchar(500) DEFAULT NULL COMMENT '更新信息',
  `target_size` varchar(10) DEFAULT NULL COMMENT 'apk安装包大小',
  `new_md5` varchar(255) DEFAULT NULL COMMENT '新apk的MD5码',
  `constraint` int(11) DEFAULT '0' COMMENT '是否强制更新,0-false;1-true',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

SET FOREIGN_KEY_CHECKS = 1;

调用方法

首先,导入基础框架的update-app库,

使用方法很简单,在AndroidBase项目的LoginActivity页面,调用检查App的更新方法。

 /**
 * 检查是否需要更新
 */
private void checkUpdate() {
    new UpdateAppManager.Builder().setActivity(this)
            // 将versionName发送给后台,后台进行版本升级判断
            .setUpdateUrl(AppContext.getInstance().getHostConfig().getmCheckUpdateUrl())
            .setHttpManager(new OkGoUpdateHttpUtil())
            .build()
            // 设置升级方式
            .silenceUpdate();
}

调用方法分析

构建UpdateAppManager作为Update-app库的入口,

通过使用UpdateAppManager的内部类Builder,完成参数的配置,最后构建出UpdateManager对象,调用更新方法。

配置参数

因为需要配置的参数比较多,UpdateAppManager使用了构造者模式,在UpdateAppManager有一个静态的内部类Builder

public static class Builder {
    //必须有
    private Activity mActivity;
    //必须有
    private HttpManager mHttpManager;
    //必须有
    private String mUpdateUrl;
    //1,设置按钮,进度条的颜色
    private int mThemeColor = 0;
    //2,顶部的图片
    private
    @DrawableRes
    int mTopPic = 0;
    //3,唯一的appkey
    private String mAppKey;
    //4,apk的下载路径
    private String mTargetPath;
    //5,是否是post请求,默认是get
    private boolean isPost;
    //6,自定义参数
    private Map params;
    //7,是否隐藏对话框下载进度条
    private boolean mHideDialog;
    private boolean mShowIgnoreVersion;
    private boolean dismissNotificationProgress;
    private boolean mOnlyWifi;
}

必须要设置的参数有三个Activity、HttpManager、UpdateUrl,当三个参数赋值完成后,调用Builder.build()的方法,创建UpdateAppManager对象。

HttpManager

这里有必要说一下HttpManager,这是一个自己定义的接口

定义了发送的请求,下载回调,网络请求回调的规范。

OkGoUpdateHttpUtil实现

生成UpdateAppManager对象

 /**
 * @return 生成app管理器
 */
public UpdateAppManager build() {
    //校验
    if (getActivity() == null || getHttpManager() == null || TextUtils.isEmpty(getUpdateUrl())) {
        throw new NullPointerException("必要参数不能为空");
    }
    if (TextUtils.isEmpty(getTargetPath())) {
        // 设置下载路径
        String path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath();
        setTargetPath(path);
    }
    // 在AndroidMenifest.xml文件中添加的AppKey,可以给后台留作验证
    // 增加了接口的安全性,可以让后台进行AppKey的校验,如果Key不对的话,就不进行下载
    // 并不是必须的
    // 如果在build的时候设置了自定义请求参数,这么这里添加的AppKey就不会传递给后台了。
    // 除非在自定义请求参数中,将这个AppKey添加进去。
    if (TextUtils.isEmpty(getAppKey())) {
        String appKey = AppUpdateUtils.getManifestString(getActivity(), UPDATE_APP_KEY);
        if (TextUtils.isEmpty(appKey)) {
        } else {
            setAppKey(appKey);
        }
    }
    // 这里的this就指的是Builder
    return new UpdateAppManager(this);
}

调用更新方法

UpdateAppManager里的的silenceUpdate()update()两个方法都是调用更新的方法,一个是静默更新,一个是最简单的更新方法,下面就来看看这两个方法的区别。

/**
 * 静默更新
 */
public void silenceUpdate() {
    checkNewApp(new SilenceUpdateCallback());
}

/**
 * 最简方式
 */

public void update() {
    checkNewApp(new UpdateCallback());
}

调用了build()方法后,直接调用的更新方法

new UpdateAppManager.Builder().setActivity(this)
                // 将versionName发送给后台,后台进行版本升级判断
                .setUpdateUrl(AppContext.getInstance().getHostConfig().getmCheckUpdateUrl())
                .setHttpManager(new OkGoUpdateHttpUtil())
                .build()
                // 调用更新方法
                .silenceUpdate();

silenceUpdate()update()方法都调用了checkNewApp(UpdateCallBack callBack)方法,我们继续分析

这里传入的是一个实现了UpdateCallBackSilenceUpdateCallback对象

/**
 * 检测是否有新版本
 *
 * @param callback 更新回调
 */
public void checkNewApp(final UpdateCallback callback) {
    if (callback == null) {
        return;
    }
    callback.onBefore();

    if (DownloadService.isRunning || UpdateDialogFragment.isShow) {
        callback.onAfter();
        Toast.makeText(mActivity, "app正在更新", Toast.LENGTH_SHORT).show();
        return;
    }

    //拼接参数
    Map params = new HashMap();

    params.put("appKey", mAppKey);
    String versionName = AppUpdateUtils.getVersionName(mActivity);
    if (versionName.endsWith("-debug")) {
        versionName = versionName.substring(0, versionName.lastIndexOf('-'));
    }
    params.put("version", versionName);


    //添加自定义参数,其实可以实现HttManager中添加
    if (mParams != null && !mParams.isEmpty()) {
        //清空默认传递的参数,使用自定参数
        params.clear();
        params.putAll(mParams);
    }

    //网络请求
    if (isPost) {
        mHttpManager.asyncPost(mUpdateUrl, params, new HttpManager.Callback() {
            @Override
            public void onResponse(String result) {
                callback.onAfter();
                if (result != null) {
                    processData(result, callback);
                }
            }

            @Override
            public void onError(String error) {
                callback.onAfter();
                callback.noNewApp();
            }
        });
    } else {
        // 默认情况下使用的是get请求方式
        mHttpManager.asyncGet(mUpdateUrl, params, new HttpManager.Callback() {
            @Override
            public void onResponse(String result) {
                callback.onAfter();
                if (result != null) {
                    // 解析服务器返回的数据
                    processData(result, callback);
                }
            }

            @Override
            public void onError(String error) {
                callback.onAfter();
                callback.noNewApp();
            }
        });
    }
}
  • parseData(String reulst, UpdateCallback callback) 解析
 private void processData(String result, @NonNull UpdateCallback callback) {
    try {
        // 解析json数据
        mUpdateApp = callback.parseJson(result);
        if (mUpdateApp.isUpdate()) {
            callback.hasNewApp(mUpdateApp, this);
            //假如是静默下载,可能需要判断,
            //是否wifi,
            //是否已经下载,如果已经下载直接提示安装
            //没有则进行下载,监听下载完成,弹出安装对话框
        } else {
            callback.noNewApp();
        }
    } catch (Exception ignored) {
        ignored.printStackTrace();
        callback.noNewApp();
    }
}

展示框FragmentDialog

如果有新版本的话,会在登录页面上新建一个FragmentDialog,用来展示本次更新的内容,以及调用APP的更新或者忽略本次版本。

protected void hasNewApp(UpdateAppBean updateApp, UpdateAppManager updateAppManager) {
    updateAppManager.showDialogFragment();
}

你可能感兴趣的:(AppUpdate分析)