业务背景:uniapp打包ios,android之后,有时候紧急修复或修改ui,还需要走应用市场审核,就会很着急,有热更之后,可以避免应用市场长时间审核,很快就能更新
热更流程
老规矩,话不多说,上码,直接复制粘贴看效果
***说明:
- 热更内容是全局使用,所以写在App.vue中,避免页面重复调用
- 更新的是wgt的资源包
- 需要有三个接口(接口控制灵活度更高)
- 判断是否需要热更新
- 确定更新,同步给接口状态
- 取消更新,同步给接口状态
- 需要有个后台管理页面(接口数据来源)
一、代码相关
看着代码多,你肯定一看就懂,耐心看下去
<script>
// 调用接口
import { getLatestVersion, ignoreVersion, confirmVersion } from "@/api/app-version/app-version";
export default {
onLaunch: function() {
// 只有App才有的事件,座椅要加上运行平台,不然在小程序端会报错
// #ifdef APP-PLUS
const deviceMsg = uni.getSystemInfoSync();
this.pubFn(deviceMsg)
// #endif
},
methods: {
pubFn(deviceMsg){
plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
// 和后台约定入参格式 主要是版本号 比如标准的版本号:001.0001
let vers = widgetInfo.version.split('.')
vers[1] = vers[1]>=100 ? vers[1] : vers[1]>=10 ? `0${vers[1]}` : `00${vers[1]}`
vers[2] = vers[2]>=1000 ? vers[2] : vers[2]>=100 ? `0${vers[2]}` : vers[2]>=10 ? `00${vers[2]}` : `000${vers[2]}`
let opt = {
appType: 1,
deviceId: deviceMsg.deviceId,
currentVersion: vers.join(''),
deviceBrand: deviceMsg.deviceBrand,
deviceModel: deviceMsg.deviceModel,
osName: deviceMsg.osName,
osVersion: deviceMsg.osVersion,
uid: uni.getStorageSync('userId')
}
// 以上都是处理入参 --END
// 接口控制是否更新 需要有对应后台管理
getLatestVersion(opt).then(data => {
// 要更新 且有更新包地址
if (data.isUpgrade) {
// 弹出 选择框 让用户选择是否更新,
uni.showModal({
content: data.description,
confirmText: "更新",
showCancel: data.isForceUpgrade ==1 ? false : true,
success: function(e) {
if (e.confirm) {
let sucOpt = {
appType: 1,
deviceId: deviceMsg.deviceId,
version: data.version
}
// 更新之后需要同步接口
confirmVersion(sucOpt)
if(data.upgradeType == 1){
if (plus.os.name == "Android") {
// 安卓下载地址,跳转各自的市场(小米、华为、OPPO等)
let appurl = "market://details?id=com.sx.supplychain"
plus.runtime.openURL(appurl)
plus.runtime.restart();
} else {
plus.runtime.openURL('itms-apps://itunes.apple.com/cn/app/id6471384534?mt=8');
plus.runtime.restart();
}
}else{
if (plus.os.name.toLowerCase() == 'ios') {
// 跳转到下载页面
uni.downloadFile({
url: data.wgtUrl,
success: (downloadResult) => {
plus.runtime.install(downloadResult.tempFilePath,{force:true},function(){
plus.runtime.restart();
});
}
});
} else {
// 下载wgtUrl的文件
var dtask = plus.downloader.createDownload(
data.wgtUrl,
{},
function(d, status) {
uni.showToast({
title: '下载完成',
mask: false,
duration: 2000
});
// 下载完成 安装 force 一定要设置为true,更新完成后 重启应用
if (status == 200) {
plus.runtime.install(plus.io.convertLocalFileSystemURL(d.filename), {
force: true
}, function() {
plus.runtime.restart();
}, function(error) {
uni.showToast({
title: '安装失败-01',
mask: false,
duration: 1500
});
})
} else {
uni.showToast({
title: '更新失败',
mask: false,
duration: 1500
});
}
});
try {
dtask.start(); // 开启下载的任务
var prg = 0;
var showLoading = plus.nativeUI.showWaiting("正在下载"); //创建一个showWaiting对象
dtask.addEventListener('statechanged', function(
task,
status
) {
// 给下载任务设置一个监听 并根据状态 做操作
switch (task.state) {
case 1:
showLoading.setTitle("正在下载");
break;
case 2:
showLoading.setTitle("已连接到服务器...");
break;
case 3:
prg = parseInt(
(parseFloat(task.downloadedSize) /
parseFloat(task.totalSize)) *
100
);
showLoading.setTitle(" 正在下载" + prg + "% ");
break;
case 4:
plus.nativeUI.closeWaiting();
//下载完成
break;
}
});
} catch (err) {
plus.nativeUI.closeWaiting();
uni.showToast({
title: '更新失败',
mask: false,
duration: 1500
});
}
}
}
}else if (e.cancel) {
let igOpt = {
appType: 1,
deviceId: deviceMsg.deviceId,
version: data.version,
isIgnore: 1
}
// 取消更新 同样需要同步接口 方便下次 继续弹或者其它逻辑
ignoreVersion(igOpt)
}
}
})
}
})
});
},
}
}
</script>
二、wgt资源包(获取wgt包文件,上传后台)
注意:打包之前需要更新版本号,必须高于上个版本号
1.更新版本号
2、打包wgt文件,顶部工具栏 — 发行 — 制作应用wgt包 — 选择保存地址
二、后台管理相关
- 热更的列表
- 新建热更