背景
现在应有不少同学在写阳光沙滩App,App的测试版本发出来给大家体验,不可能每次都这样发,比较麻烦,app内置升级功能是必不可少的,这一次就分享下,如何做简单的App内置升级
需要的工具
- 一台远程服务器
- nginx
- 上面2个东西,如果做过博客系统的,都应该有的
分析升级功能
- 升级就是对比版本号,低于就提示升级
- 版本号的数据放哪里?直接挂nginx配置的html中文件夹中,类似于index.html提供公网访问
- 有了升级的配置,apk放哪里,和上面同理
- App端如何实现?使用升级工具下载和对比版本,不过这些都是使用第三方实现,一句代码 -
服务器存放升级数据和apk
打开我们filezilla,链接我们服务器,进入nginx挂的目录wwwroot,在mp中创文件夹apk

一定要读写权限,不然无法访问,做了自动化部署的,要记得保留这个目录
放到这里之后,我们通过ip或者域名直接访问,就能下载apk了,至于速度,看你财力。
//我的apk地址
http://mp.moonlightshadow.cn/apk/release_v_1.0.7.beta.apk
下次上传apk直接修改版本就行了,依次地增加。
apk放好了,我们开始放升级文件json
{
  "Code": 0,
  "Msg": "",
  "UpdateStatus": 1,
  "VersionCode": 14,
  "VersionName": "1.0.7.beta",
  "UploadTime": "2018-07-10 17:28:41",
  "ModifyContent": "\r\n1、升级多个官方组件\r\n2、修复已知未知bug,把程序员哥哥打了一顿\r\n3、如果发现bug希望反馈给我哦",
  "DownloadUrl": "http://mp.moonlightshadow.cn/apk/release_v_1.0.7.beta.apk",
  "ApkSize": 13060,
  "ApkMd5": "36d7bbad4a253b2658674fb530c7e391"
}
这个json,写个名字,保存.json。或者任意都可以,和apk一样,丢服务器中。 访问这个地址的时候,就得到我们的json数据了,最简单接口,完成了
http://mp.moonlightshadow.cn/apk/sob_update.json
大家可以访问接口试试

接口准备好了,就开始App部分。
App升级实现简单版
implementation 'com.github.xuexiangjys:XUpdate:2.0.7'
implementation 'com.zhy:okhttputils:2.6.2'
借助大佬的升级工具,直接起飞。如果你自己想实现也是可以的,访问接口,得到版本号,对比是否升级,下载apk文件,对比文件md5,调起安装,没做过可以自己试试,我是做的过多,能最简单实现就行,这个库我接在公司项目中,使用一年了。挺稳的。
App需要的代码不多,第一依赖上面库。
Application中
onCreate()中增加方法
    private fun initAppUpdate() {
        XUpdate.get()
            .debug(BuildConfig.DEBUG)
            .isWifiOnly(false) // By default, only version updates are checked under WiFi
            .isGet(true) // The default setting uses Get request to check versions
            .isAutoMode(false) // The default setting is non automatic mode
            .param(
                "versionCode",
                UpdateUtils.getVersionCode(this)
            ) // Set default public request parameters
            .param("appKey", packageName)
            .setOnUpdateFailureListener { error ->
                // Set listening for version update errors
                if (error.code != CHECK_NO_NEW_VERSION) {          // Handling different errors
                }
            }
            .supportSilentInstall(true) // Set whether silent installation is supported. The default is true
            .setIUpdateHttpService(OKHttpUpdateHttpService()) // This must be set! Realize the network request function.
            .init(this)
    }
直接复制代码,或者去github上面看文档。
OKHttpUpdateHttpService
public class OKHttpUpdateHttpService implements IUpdateHttpService {
    private boolean mIsPostJson;
    public OKHttpUpdateHttpService() {
        this(false);
    }
    public OKHttpUpdateHttpService(boolean isPostJson) {
        mIsPostJson = isPostJson;
    }
    @Override
    public void asyncGet(@NonNull String url, @NonNull Map<String, Object> params, final @NonNull Callback callBack) {
        get()
                .url(url)
                .params(transform(params))
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        callBack.onError(e);
                    }
                    @Override
                    public void onResponse(String response, int id) {
                        callBack.onSuccess(response);
                    }
                });
    }
    @Override
    public void asyncPost(@NonNull String url, @NonNull Map<String, Object> params, final @NonNull Callback callBack) {
        //这里默认post的是Form格式,使用json格式的请修改 post -> postString
        RequestCall requestCall;
        if (mIsPostJson) {
            requestCall = postString()
                    .url(url)
                    .content(new Gson().toJson(params))
                    .mediaType(MediaType.parse("application/json; charset=utf-8"))
                    .build();
        } else {
            requestCall = post()
                    .url(url)
                    .params(transform(params))
                    .build();
        }
        requestCall
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        callBack.onError(e);
                    }
                    @Override
                    public void onResponse(String response, int id) {
                        callBack.onSuccess(response);
                    }
                });
    }
    @Override
    public void download(@NonNull String url, @NonNull String path, @NonNull String fileName, final @NonNull DownloadCallback callback) {
        get()
                .url(url)
                .tag(url)
                .build()
                .execute(new FileCallBack(path, fileName) {
                    @Override
                    public void inProgress(float progress, long total, int id) {
                        callback.onProgress(progress, total);
                    }
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        callback.onError(e);
                    }
                    @Override
                    public void onResponse(File response, int id) {
                        callback.onSuccess(response);
                    }
                    @Override
                    public void onBefore(Request request, int id) {
                        super.onBefore(request, id);
                        callback.onStart();
                    }
                });
    }
    @Override
    public void cancelDownload(@NonNull String url) {
        getInstance().cancelTag(url);
    }
    private Map<String, String> transform(Map<String, Object> params) {
        Map<String, String> map = new TreeMap<>();
        for (Map.Entry<String, Object> entry : params.entrySet()) {
            map.put(entry.getKey(), entry.getValue().toString());
        }
        return map;
    }
}
MainActivity,或者是你需要升级的act中,或者fragment中。
XUpdate.newBuild(this)
                .updateUrl(AppConstant.UPDATE_URL + System.currentTimeMillis())
                .update()
AppConstant.UPDATE_URL就是我们的json地址
http://mp.moonlightshadow.cn/apk/sob_update.json?r=
一定要加个随机数,不然会有缓存的,更新了json文件App无法升级的,记得一定要加随机数
上面说的几个步骤都不难,就是需要服务器配合。
{
  "Code": 0,
  "Msg": "",
  "UpdateStatus": 1,//1提示更新,0不更新不提示,2强制,每次升级你修改这个配置就行了
  "VersionCode": 14,//客户端版本号,根据这个来升级对比的。
  "VersionName": "1.0.7.beta",//名字随便
  "UploadTime": "2018-07-10 17:28:41",//时间可以不写
  "ModifyContent": "\r\n1、升级多个官方组件\r\n2、修复已知未知bug,把程序员哥哥打了一顿\r\n3、如果发现bug希望反馈给我哦",//内容随意
  "DownloadUrl": "http://mp.moonlightshadow.cn/apk/release_v_1.0.7.beta.apk",//这个是你自己服务器地址,如果不是https记得允许http访问哦
  "ApkSize": 13060,//大小可以不准确
  "ApkMd5": "36d7bbad4a253b2658674fb530c7e391"//apk的md5,自己取,有工具。可以使用我现在的工具
}
http://mp.moonlightshadow.cn/apk/MD5_Tool.exe,杀毒软件会杀了它,记得放行
简单的升级就是这样了,希望写阳光沙滩App的同学,都把升级功能加上,大家升级方便,如果你有理想的靓仔,就可以使用服务器通过博客那一套搞,加个表记录升级信息,开个接口查询更新信息,加个web页面填写升级信息和上传apk,apk上传记得打开nginx的文件大小限制和博客系统项目配置文件大小,不然上传不了的。再把上传权限做了就行了。
总结
简易的升级使用到技术不多,上面是我临时想到方案,实现起来半个小时吧,哈哈。希望大家可以做出更漂亮的阳光沙滩。



 断点-含光君  回复 @码划云
 断点-含光君  回复 @码划云 































