背景
现在应有不少同学在写阳光沙滩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的文件大小限制和博客系统项目配置文件大小,不然上传不了的。再把上传权限做了就行了。
总结
简易的升级使用到技术不多,上面是我临时想到方案,实现起来半个小时吧,哈哈。希望大家可以做出更漂亮的阳光沙滩。