我们做的比较简单,在后端设置版本号,并在uniapp的config.js中定义版本号,每次跟后端的进行对比,不一致的话就更新。
一、下载apk
主要代码(下载安装包,并进行安装,一般得手动同意安装)
const uploadTask = uni.downloadFile({ // 下载apk/资源包
url: 'xxx',//下载apk的地址
success: (downloadResult) => {
console.log(downloadResult);
if (downloadResult.statusCode === 200) {
// uni.clearStorage()
plus.runtime.install(downloadResult.tempFilePath, {
force: true
},
function() {
plus.runtime.restart(); // 重启APP
},
function(e) {
_this.show = false
uni.showToast({
title: e.message,
icon: 'none'
})
});
} else {
_this.show = false
if (_this.updateType === 1) {
uni.showToast({
title: '资源包下载失败',
duration: 2000,
icon: 'error'
})
} else {
uni.showToast({
title: 'APK下载失败',
duration: 2000,
icon: 'error'
})
}
}
}
});
二、监听下载进度
//监听下载进度
uploadTask.onProgressUpdate((res) => {
_this.updateProgress = res.progress //下载进度 0-100
if (_this.updateType === 1) {
if (res.progress > 95) {
// _this.restartFlag = true
}
}
});
三、全部代码
dialog.vue
<template>
<view class="uploadCon" v-if="show">
<view class="uploadBox">
<!-- 版本信息弹窗 -->
<view class="dialogBox">
<view class="circle">
<image src="@/static/images/icons/upload.png" mode="widthFix">
</image>
</view>
<view class="needLoad" v-if="versionsFlag === 1">
<view class="title">
{{updateType === 1?'最新资源包':'发现新版本'}} V{{getVersion}}
</view>
<view class="tips">
<view>电子秤检测到新版本,请更新后使用!</view>
</view>
<view class="buttonCon">
<!-- <view class="button button2" @click="show = false">暂不更新</view> -->
<view class="button button1" @click="updateNow">立即更新</view>
</view>
</view>
<view class="loadingBox" v-if="versionsFlag === 3">
<view class="title">正在下载,请稍后 </view>
<view>
<progress :percent="updateProgress" show-info stroke-width="20" />
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import {
appInfo,
} from "@/config.js"
import {
uploadSys
} from "@/api/system/user.js"
import {
getToken
} from "@/api/login.js"
export default {
data() {
return {
// 版本更新相关
version: '', //版本名称
versionCode: '', //版本号 当前
getVersion:'',//最新版本
apkUpdateContent: '', //更新内容说明
updateType: '', //1资源包更新2版本更新
versionsFlag: 1, //1需要更新弹窗2已是最新版本弹窗3正在下载
latestVersionInfo: '', //已是最新版本弹窗内容
updateAPKPath: '', //下载文件路径
updateProgress: 0, //下载进度
restartFlag: false,
show: false
}
},
mounted() {
this.update();
},
methods: {
update() {
let _this = this
let platform = uni.getSystemInfoSync().platform
let server = '***********************'
let signServer = '***********************'
// 当前版本信息
this.versionCode = appInfo.version; //版本号
uploadSys({}).then(response => {
this.getVersion = response.rows[0].dictValue;
if (this.versionCode == this.getVersion) {
//已经是最新版本
} else {
this.show = true
//要更新
this.versionsFlag = 1;
}
})
},
//弹窗点击确认更新以后
updateNow() {
let _this = this
_this.versionsFlag = 3
const uploadTask = uni.downloadFile({ // 下载apk/资源包
url: 'xxx',//apk下载地址,更换成你自己的
success: (downloadResult) => {
console.log(downloadResult);
if (downloadResult.statusCode === 200) {
// uni.clearStorage()
plus.runtime.install(downloadResult.tempFilePath, {
force: true
},
function() {
plus.runtime.restart(); // 重启APP
},
function(e) {
_this.show = false
uni.showToast({
title: e.message,
icon: 'none'
})
});
} else {
_this.show = false
if (_this.updateType === 1) {
uni.showToast({
title: '资源包下载失败',
duration: 2000,
icon: 'error'
})
} else {
uni.showToast({
title: 'APK下载失败',
duration: 2000,
icon: 'error'
})
}
}
}
});
//监听下载进度
uploadTask.onProgressUpdate((res) => {
_this.updateProgress = res.progress
if (_this.updateType === 1) {
if (res.progress > 95) {
// _this.restartFlag = true
}
}
});
},
}
}
</script>
<style scoped lang="scss">
@import "@/static/scss/dialog.scss";
</style>
dialog.scss
.uploadCon{
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
z-index: 100;
background-color: rgba(0,0,0,0.6);
.uploadBox{
position: fixed;
width: 24%;
height: 40%;
top: 30%;
left: 38%;
z-index: 1000;
background-image: -webkit-linear-gradient(top, #fff,#f4f8ff, #e4ecfb, #c7d9fc);
border: 1px solid #fff;
border-radius: 15rpx;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
.dialogBox{
display: flex;
flex-direction: column;
padding: 10% 15% 0%;
height: 67%;
position: relative;
.needLoad{
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.loadingBox{
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.circle{
position: absolute;
left: 0;
right: 0;
width: 14vh;
height: 14vh;
margin: 0 auto;
top: -7vh;
background-color: #fff;
border-radius: 100%;
display: flex;
justify-content: center;
align-items: center;
image{
width: 8vh;
}
}
.title{
margin-top: 30rpx;
text-align: center;
// line-height: 90rpx;
font-size: 50rpx;
font-weight: bold;
}
.buttonCon{
display: flex;
justify-content: space-between;
.button{
line-height: 90rpx;
border-radius: 10rpx;
text-align: center;
width: 100%;
font-size: 34rpx;
}
.button1{
background-color: #336edf;
color: #fff;
}
.button2{
background-color: #fff;
color: #7d7d7d;
}
.tips{
font-size: 34rpx;
line-height: 60rpx;
}
}
}
}
}
四、下载到安卓指定位置
uni.downloadFile设置下载文件的路径,但不能指定下载到设备的某个路径下,用plus.downloader.createDownload可以实现,代码还提供了替换功能。
代码如下:
//下载人脸文件
updateNow() {
this.saveFileWithCN('https://xxx/statics/datFile/Users.dat', 'Users.dat')
},
saveFileWithCN(fileUrl, customFileName) { // 文件下载地址, 自定义文件名
const defaultPathPrefix = "/sdcard/Documents"; //下载到内存Documents文件下
const fullPath = `${defaultPathPrefix}/${customFileName}`;
console.log(fullPath)
// 3. 检查并删除已存在的文件(实现替换功能)
const File = plus.android.importClass('java.io.File');
const targetFile = new File(fullPath);
// uni.showLoading({
// title: '核心文件下载中...',
// mask: true
// });
this.tips = '核心文件下载中...';
if (targetFile.exists()) {
targetFile.delete(); // 删除旧文件
console.log("已删除旧文件:", fullPath);
}
const dtask = plus.downloader.createDownload(fileUrl, {
filename: fullPath
}, (d, status) => {
if (status === 200) {
console.log("保存路径:", d.filename);
this.tips = '核心文件下载完成!';
uni.setStorageSync('update',true);
this.initFaceModule();
setTimeout(() => {
this.tips = ''
}, 1000)
} else {
this.tips = '核心文件下载失败!';
setTimeout(() => {
this.tips = ''
}, 1000)
}
});
dtask.start();
},
五、运行结果

