upgrade.js
javascript
/**
* @description H5+下载App
* @param downloadUrl:App下载链接
* @param progressCallBack:下载进度回调
*/
export const downloadApp = (downloadUrl, progressCallBack = () => {}, ) => {
return new Promise((resolve, reject) => {
//创建下载任务
const downloadTask = plus.downloader.createDownload(downloadUrl, {
method: "GET"
}, (task, status) => {
console.log(status,'status')
if (status == 200) { //下载成功
resolve(task.filename)
} else {
reject('fail')
uni.showToast({
title: '下载失败',
duration: 1500,
icon: "none"
});
}
})
//监听下载过程
downloadTask.addEventListener("statechanged", (task, status) => {
switch (task.state) {
case 1: // 开始
break;
case 2: //已连接到服务器
break;
case 3: // 已接收到数据
let hasProgress = task.totalSize && task.totalSize > 0 //是否能获取到App大小
if (hasProgress) {
let current = parseInt(100 * task.downloadedSize / task.totalSize); //获取下载进度百分比
progressCallBack(current)
}
break;
case 4: // 下载完成
break;
}
});
//开始执行下载
downloadTask.start();
})
}
/**
* @description H5+安装APP
* @param fileName:app文件名
* @param callBack:安装成功回调
*/
export const installApp = (fileName, callBack = () => {}) => {
//注册广播监听app安装情况
onInstallListening(callBack);
//开始安装
plus.runtime.install(plus.io.convertLocalFileSystemURL(fileName), {}, () => {
//成功跳转到安装界面
}, function(error) {
uni.showToast({
title: '安装失败',
duration: 1500,
icon: "none"
});
})
}
/**
* @description 注册广播监听APP是否安装成功
* @param callBack:安装成功回调函数
*/
const onInstallListening = (callBack = () => {}) => {
let mainActivity = plus.android.runtimeMainActivity(); //获取activity
//生成广播接收器
let receiver = plus.android.implements('io.dcloud.android.content.BroadcastReceiver', {
onReceive: (context, intent) => { //接收广播回调
plus.android.importClass(intent);
mainActivity.unregisterReceiver(receiver); //取消监听
callBack()
}
});
let IntentFilter = plus.android.importClass('android.content.IntentFilter');
let Intent = plus.android.importClass('android.content.Intent');
let filter = new IntentFilter();
filter.addAction(Intent.ACTION_PACKAGE_ADDED); //监听APP安装
filter.addDataScheme("package");
mainActivity.registerReceiver(receiver, filter); //注册广播
}
update_mask.vue
javascript
<template>
<view>
<view class="update-mask" v-if="show || showPrgress">
<view class="update-wrap" v-if="show">
<view class="update-title">发现新版本</view>
<view class="update-version">v{{ dataInfo.appVersion }}</view>
<view class="update-conent">
<!-- <view class="update-con-title">更新内容:</view> -->
<view class="update-con-p">
<view class="update-p">尊敬的用户:</view>
<view class="update-p">您当前版本V{{ systemVersion }},为了提供更好的用户体验和功能改进,我们应用需要进行强制更新,请尽快更新至最新版本以获得最新功能和改进。感谢您的理解与支持!</view>
</view>
</view>
<button class="update-btn" v-if="!btnDisable" @click="gotoUpdate">
立即更新
</button>
<view class="progress-view" @click="handleInstallApp" v-else-if="btnDisable">
<view v-if="showPrgress" style="height: 100%;">
<view class="txt">{{percentText}}</view>
<view class="progress" :style="{
width: `${progress}%`
}"></view>
</view>
<button class="update-finish" v-else>
{{ isDownloadFinish ? '立即安装' :'下载中...'}}
</button>
</view>
</view>
</view>
</view>
</template>
<script>
import { getAppVersion } from '@/api/api.js'
import {
downloadApp,
installApp
} from './upgrade.js'
export default {
components: {},
data() {
return {
show: false,
info: "",
dataInfo: "",
showPrgress: false,
progress: 0,
percentText: '下载中',
isDownloadFinish: false,
btnDisable: false,
systemVersion:"",
testData:"",
fileName: "",//文件名称
}
},
watch: {},
async mounted() {
// 大版本更新
this.getUplate();
},
methods: {
getUplate(){
uni.hideLoading();
let that = this;
const info = uni.getSystemInfoSync()
const systemVersion = plus.runtime.version
that.systemVersion = systemVersion;
let updateStatus = ""
getAppVersion().then(res => {
let status = res.status;
let data = res.data;
if (status === 200 && data) {
if (data.androidAddress) {
if (data.androidAddress.indexOf('.apk') > -1) {
const nowVersion = systemVersion.split('.').join('')
let appVersion = data.appVersion.split('.').join('')
console.log("当前版本",nowVersion)
console.log("线上版本",appVersion)
console.log("是否更新",nowVersion < appVersion)
if (nowVersion < appVersion) {
uni.hideTabBar();
updateStatus = 'apk';
that.updateMet(updateStatus,info,data);
}
}
}
}
})
},
updateMet(updateStatus,info,data){
if(updateStatus == 'apk' || updateStatus == 'wgt'){
this.show = true;
this.info = info;
this.dataInfo = data;
this.updateStatus = updateStatus;
}
},
// 开始更新
gotoUpdate(){
this.btnDisable = true;
if(this.updateStatus == 'apk'){
this.apkUpdate(this.info, this.dataInfo);
}
},
//安装app
handleInstallApp() {
//下载完成才能安装,防止下载过程中点击
if (this.isDownloadFinish && this.fileName) {
installApp(this.fileName, () => {
//安装成功,关闭升级弹窗
// uni.navigateBack()
})
}
},
apkUpdate(info, data){
let that = this;
downloadApp(data.androidAddress, current => {
that.showPrgress = true;
that.progress = current;
that.percentText = `下载中${current}%`
}).then(fileName => {
//下载完成
that.isDownloadFinish = true;
that.percentText = `下载完成`
that.showPrgress = false;
that.fileName = fileName
if (fileName) {
//自动安装App
that.handleInstallApp()
}
}).catch(e => {
console.log(e, 'e')
})
},
},
}
</script>
<style lang="scss" scoped>
$btn-height: 80rpx;
.update-mask{
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
background: rgba(0,0,0,0.3);
z-index: 99999;
.update-wrap{
background: #fff;
color: #000;
position: absolute;
width: 80%;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
padding: 40rpx;
border-radius: 20rpx;
letter-spacing: 2rpx;
}
.update-title{
font-size: 38rpx;
margin-bottom: 6rpx;
}
.update-version{
font-size: 28rpx;
margin-bottom: 60rpx;
margin-top: 6rpx;
}
.update-conent{
font-size: 24rpx;
}
.update-con-p{
margin: 30rpx 0;
}
.update-p{
line-height: 40rpx;
}
.update-btn{
background: #43CF7C;
text-align: center;
color: #fff;
height: $btn-height;
line-height: $btn-height;
border-radius: 6rpx;
position: relative;
font-size: 32rpx;
}
}
.progress-view {
width: 100%;
height: $btn-height;
display: flex;
position: relative;
align-items: center;
border-radius: 6rpx;
background-color: rgba(255,255,255,0.4);
display: flex;
justify-content: flex-start;
overflow: hidden;
border: 1px solid #43CF7C;
.progress {
height: 100%;
background-color: rgba(67,207,124,0.3);
padding: 0px;
box-sizing: border-box;
width: 20%;
position: absolute;
top: 0;
left: 0;
}
.txt {
font-size: 28rpx;
position: absolute;
top: 50%;
left: 50%;
z-index: 10;
transform: translate(-50%, -50%);
color: #43CF7C;
}
.update-finish{
position: absolute;
width: 100%;
height: 100%;
text-align: center;
line-height: $btn-height;
color: #43CF7C;
font-size: 28rpx;
}
}
</style>
wgt更新
wgtUpdate.js
javascript
function wgtUpdate(data){
uni.downloadFile({
url: data.androidAddress,
success: downloadResult => {
if (downloadResult.statusCode === 200) {
plus.runtime.install(
downloadResult.tempFilePath,
{
force: false
},
function () {
console.log('install success...')
plus.runtime.restart()
},
function (error) {
uni.showModal({
title: '更新失败',
content: error.message,
confirmText: '我知道了',
showCancel: false
})
console.error('install fail...')
}
)
}
}
})
}
export default wgtUpdate
app.vue
javascript
<script>
import wgtUpdate from "@/utils/update/wgtUpdate";
import { getAppVersion } from '@/api/api.js';
export default {
globalData: {},
onLaunch: function(option) {
getAppVersion().then(res => {
let status = res.status;
let data = res.data;
if (status === 200 && data) {
if(data.androidAddress.indexOf('.wgt') > -1) {
plus.runtime.getProperty(plus.runtime.appid, function (widgetInfo) {
if (widgetInfo.version < data.appVersion) {
wgtUpdate(data)
}
})
}
}
})
},
onShow() {
},
methods: {
},
}
</script>
<style lang="scss">
</style>