啊~时隔多月终于闲下来了。最近整理了下资料发现热更新在app开发是经常见的,基本必备而且确实很方便,所以就总结了点东西给大家看看,有问题可以一起讨论
需要服务器存放更新包资源,后端提供接口用于检测当前版本是否为最新版本。(增删改查)
热更新的流程其实很简单,如下图所示
// 保存 app 版本信息
// #ifdef APP-PLUS
plus.runtime.getProperty(plus.runtime.appid, (widgetInfo)=> {
// console.log('widgetInfo', widgetInfo);
this.version = widgetInfo.version;
});
// #endif
checkWgtFun() {
//loginApi.getPatchManage() 获取更新包接口
loginApi.getPatchManage().then(res=> {
console.log('检查更新包', res);
if(res.code == 200) {
let result = res.data.versionNum // 更新包版本
if(this.version.substr(0, 3) * 1 >= result.substr(0, 3) * 1){
this.$toast('当前为最新版本');
return
}
if(this.version.replace(/\./g, "") * 1 >= result.replace(/\./g, "") * 1){
this.$toast('当前为最新版本');
return
}
uni.showModal({
title: '提示',
content: '发现有新版本可以升级',
cancelText: '取消更新',
confirmText: '立即更新',
success: res1 => {
if (res1.confirm) {
console.log('用户点击确定');
// 补丁下载安装
// this.versionNum=res.data.versionNum
this.downWgt(res.data.patchUrl)
} else if (res1.cancel) {
console.log('用户点击取消');
}
},
fail: (err) => {
console.log('下载失败', err);
}
});
} else {
this.$toast(res.msg);
}
})
},
// 下载补丁
// patchUrl 更新包下载路径
downWgt(patchUrl) {
let _this=this
this.downloadTask = uni.downloadFile({
url:patchUrl,
success: (downloadResult) => {
if (downloadResult.statusCode === 200) {
// 安装应用
plus.runtime.install(
downloadResult.tempFilePath,
{force: false},
()=> {
plus.nativeUI.toast('最新版本下载完成')
// 安装成功之后关闭应用重启app
plus.runtime.restart();
}, (e)=> {
plus.nativeUI.toast("补丁安装失败")// 常见问题:版本号,appId
});
}
},
fail: (err) => {
plus.nativeUI.toast("补丁下载失败")
}
})
},
// 用户取消更新,中断下载
cancel() {
if(this.downloadTask) {
this.$toast('取消下载安装!')
this.downloadTask.abort()
this.downloadTask = null
}
},
<template>
<view>
<view @click="checkApp" v-if="verShow">
<u-cell-item title="检查新版本" :value='version' :arrow='false'></u-cell-item>
</view>
<u-mask :show="show">
<view class="warp">
<view class="version">
<view class="new-version">发现新版本</view>
<view style="color: #fff;">v {{versionNum}}</view>
<view class="be-updating">正在更新</view>
<u-line-progress :percent='schedule.progress' :show-percent='false' active-color='#4B86FE' striped striped-active></u-line-progress>
<view class="down-prog">{{schedule.totalBytesWritten}}/{{schedule.totalBytesExpectedToWrite}}</view>
<view class="cancel" @click="cancel">取消升级</view>
</view>
</view>
</u-mask>
</view>
</template>
<script>
import {mineApi,loginApi} from '@/api/myAjax.js'
import filters from '@/common/filters.js'
export default {
props:{
verShow:{
type:Boolean,
default:true
},
},
data() {
return {
versionNum:'',
schedule:{},
show: false,
downloadTask:null,
time:10,
isCheck:false
// versionText:''
};
},
computed:{
version() {
// 获取版本号(在其他地方需要用到所以存了全局变量)
return getApp().globalData.version
}
},
methods:{
// 检查补丁更新
checkWgtFun() {
loginApi.getPatchManage().then(res=> {
console.log('检查补丁更新包', res);
console.log('' , uni.getStorageSync('appVersion'));
if(res.code == 200) {
let result = res.data.versionNum
if(this.version.substr(0, 3) * 1 > result.substr(0, 3) * 1){
if(this.verShow){
this.$toast('当前为最新版本');
}
return
}
if(this.version.replace(/\./g, "") * 1 >= result.replace(/\./g, "") * 1){
if(this.verShow){
this.$toast('当前为最新版本');
}
return
}
uni.showModal({
title: '提示',
content: '发现有新版本可以升级',
cancelText: '取消更新',
confirmText: '立即更新',
success: res1 => {
if (res1.confirm) {
console.log('用户点击确定');
console.log(res);
// 补丁下载安装
this.versionNum=res.data.versionNum
this.downWgt(res.data.patchUrl)
} else if (res1.cancel) {
console.log('用户点击取消');
}
},
fail: (err) => {
console.log('下载失败', err);
}
});
} else {
this.isCheck = false
}
})
},
// 下载补丁
downWgt(patchUrl) {
let _this=this
console.log(patchUrl);
this.isCheck = false
this.show = true
this.downloadTask = uni.downloadFile({
url:patchUrl,
success: (downloadResult) => {
if (downloadResult.statusCode === 200) {
// 安装应用
plus.runtime.install(downloadResult.tempFilePath, {force: false}, ()=> {
_this.show =false
plus.nativeUI.toast('最新版本下载完成')
// 安装成功之后重启
plus.runtime.restart();
}, (e)=> {
_this.show =false
plus.nativeUI.toast("补丁下载失败")
});
}
},
fail: (err) => {
_this.show =false
plus.nativeUI.toast("补丁下载失败")
}
})
this.downloadTask.onProgressUpdate((res) => {
// 当前下载进度
if(this.time%10==0){
this.schedule=res
this.schedule.totalBytesExpectedToWrite=filters.sizeMB(res.totalBytesExpectedToWrite)
this.schedule.totalBytesWritten=filters.sizeMB(res.totalBytesWritten)
}
this.time+=1
});
},
// 关闭蒙层 中断下载
cancel() {
if(this.downloadTask) {
this.$toast('取消下载安装!')
this.downloadTask.abort()
this.downloadTask = null
this.show=false
this.schedule={}
}
},
}
}
</script>
<style lang="scss" scoped>
.version{
width: 521rpx;
height: 583rpx;
font-size: 24rpx;
padding: 207rpx 44rpx 33rpx;
background: url(/static/mine/gxt.png) no-repeat;
background-size: 100% 100%;
.new-version{
font-size: 30rpx;
color: #fff;
margin-bottom: 7rpx;
height: 45rpx;
line-height: 45rpx;
}
.be-updating{
margin-top: 96rpx;
margin-bottom: 14rpx;
}
.down-prog{
margin: 14rpx 0;
}
.cancel{
text-align: right;
color: #2CA6F8;
}
}
</style>
filters.js文件
function sizeMB(size){
if(size<1024){
return size+'B';
}else if(size/1024>=1 && size/1024/1024<1){
return Math.floor(size/1024*100)/100+'KB';
}else if(size/1024/1024>=1){
return Math.floor(size/1024/1024*100)/100+'MB';
}
}
export default {
sizeMB
}