uniapp每次修改了代码,或是增加了功能都得重新打包,显得尤为麻烦,所以做了个自动更新的功能。同时在web端做个二维码,可以扫码下载app软件(大体逻辑就是需要做个文件上传功能,将app打包后的apk上传至服务器,然后后端将apk包的路径返回给前端,前端拿到借助第三方插件生成二维码,扫码实现下载),web端具体操作这篇暂先不讲。下面说下app端实现自动更新的功能
开始之前先说一下打包的时候注意我们要修改:1、应用版本名称(1.0.0 升级时必须高于上一次设置)2、应用版本号(应用版本号,必须是整数;升级时必须高于上一次设置的值,这样在更新app的需要下载最新的包才不会出问题) 如下图:
接下来先说下app版本更新的思路:
首先从后端获取到最新的版本号(当然这个也是维护上的,每次重新打包了,就要去维护一个最新版本号) ,获取到之后去跟现在的版本号对比(现在的版本号我们可以通过plus.runtime.getProperty获得,详见官网:https://uniapp.dcloud.net.cn/collocation/manifest.html#%E9%85%8D%E7%BD%AE%E9%A1%B9%E5%88%97%E8%A1%A8,再进行下一步对比),如果不一样,就进行更新,如果一样就给出个提示个:当前为最新版本!
app往往在关于我们的页面会有版本更新操作,还有一种情况是,我们要不要强制更新,一般后端都要去加个字段,就是标识着要不要强制更新,如果是强制更新这种,那还得在刚进入到app的时候就进行版本的检测对比,如果版本和最大版本不一致,就必须更新,不更新的话就用不了该app,如果版本一致就不需要做提示了,其实逻辑基本一样,就是在刚进入页面检测版本的时候,如果版本一直就不需要更新了
下面贴一下核心代码
1. 首先是获取app当前的版本信息、版本号:
void plus.runtime.getProperty( appid, getPropertyCB );
参数:
- appid: ( String ) 必选 应用的Appid
- getPropertyCB: ( GetPropertyCallBack ) 必选 获得应用信息成功回调函数
示例:
// 获取应用信息
function getAppInfo() {
plus.runtime.getProperty( plus.runtime.appid, function ( wgtinfo ) {
//appid属性
var wgtStr = "appid:"+wgtinfo.appid;
//version属性
wgtStr += "<br/>version:"+wgtinfo.version;
//name属性
wgtStr += "<br/>name:"+wgtinfo.name;
//description属性
wgtStr += "<br/>description:"+wgtinfo.description;
//author属性
wgtStr += "<br/>author:"+wgtinfo.author;
//email属性
wgtStr += "<br/>email:"+wgtinfo.email;
//features 属性
wgtStr += "<br/>features:"+wgtinfo.features;
console.log( wgtStr );
} );
}
2. 上面是具体的使用,接下来我们可以在App.vue中的onLanch回调钩子中来获取当前版本号:
App.vue
onLaunch: function() {
// #ifdef APP-PLUS
this.getAppInfo()
// #endif
},
methods: {
getAppInfo() {
plus.runtime.getProperty(plus.runtime.appid, wgtinfo => {
uni.setStorageSync('version', wgtinfo.version)
})
}
}
这样之后,我们在使用的时候就可以直接从uniapp的Storage中取了
3. 接下来贴一下版本更新的核心代码:
// 获取最新版本
getMaxVersion() {
const { maxVersion } = PersonService;
uni.getSystemInfo({
success: (res) => {
const { platform } = res; // ios、android、mac(3.1.10+)、windows(3.1.10+)、linux(3.1.10+)
const map = {
android: "android",
ios: "ios",
};
// 向后端获取最新版本信息
maxVersion({ type: map[platform] }).then(({ data }) => {
this.updateVersion(data); // 自动检测版本是否需要更新
});
},
});
},
// 版本对比
updateVersion({ version, is_force_update, url }) {
const curVersion = uni.getStorageSync("version"); // 当前版本
if (curVersion) {
if (curVersion != version) {
const isShowCancel = is_force_update == "true" ? false : true;
this.showFly(isShowCancel, url);
} else {
// 这个else也就是当前的版本是最新的,如果是在更进入app的时候就不需要提示了
uni.showToast({
title: "当前为最新版本!",
icon: "none",
duration: 1600,
});
}
}
},
// 版本下载 升级
showFly(isShowCancel, url) {
uni.showModal({
title: "提示",
content: "发现新版本,立即升级!",
showCancel: isShowCancel, // 如果是强制更新就不显示取消按钮
success: (e) => {
if (e.confirm) {
uni.showLoading({
title: "更新中……",
});
const downloadTask = uni.downloadFile({
url: SERVER_URL.replace("/app", "") + url, // 这个是最新版本apk包的地址
success: (res) => {
uni.hideLoading();
if (res.statusCode === 200) {
plus.runtime.install(res.tempFilePath, { force: true }, _res => {
uni.showToast({
title: "更新成功,重启中",
duration: 1600,
});
plus.runtime.restart();
uni.hideToast();
}
);
} else {
uni.showToast({
title: "下载失败!",
icon: "none",
duration: 800,
});
}
},
});
downloadTask.onProgressUpdate((res) => {
// _this.startDown = true;
// _this.calcPro(res.progress);
// console.log('下载进度' + res.progress);
// console.log('已经下载的数据长度' + res.totalBytesWritten);
// console.log('预期需要下载的数据总长度' + res.totalBytesExpectedToWrite);
// 测试条件,取消下载任务。
// if (res.progress > 50) {
// downloadTask.abort();
// }
});
}
},
});
}
注意:
只要使用到 plus 的 最好都加上条件编译,也就是:
// #ifdef APP-PLUS
console.log(plus)
// #endif
要不然运行在浏览器也就是h5端测试会有报错。