总体来说uniapp的跨平台还是很不错的,虽然里面各种坑要去踩,但是踩坑也是开发人员的必修课和成长路。
这不,今天就来研究了一下版本检查更新就踩到坑了。。。先来看看检查更新及下载、安装的实现。
先来看看页面:
从左到右依次为检查到版本更新,下载安装过程,下载完成提示安装。
来看看uniapp的代码实现:
在启动页面或者是你认为合适的页面添加以下方法并调用:
checkVersion() {//模拟接口获取最新版本号,版本号固定为整数let platform = uni.getSystemInfoSync().platform.toLocaleLowerCase() //手机平台
//根据你们的检查接口来具体书写,我们是根据包名来管理检查的let pname = nullif (platform == 'ios') {pname = '你的IOS包名'} else {pname = '你的安卓包名'}let self = this//云打包时读取版本号plus.runtime.getProperty(plus.runtime.appid, function(wgtinfo) {
//调用接口服务获取线上版本信息getVersion(pname).then(res => {const newVersionName = res.versionName //线上最新版本名const newVersionCode = res.versionCode; //线上最新版本号const selfVersionCode = parseInt(wgtinfo.versionCode) //当前App版本号const durl = res.urllet isForceUpdate = res.type == 2//线上版本号高于当前,进行在线升级if (selfVersionCode < newVersionCode) {uni.hideLoading()self.pushActivity('/pages/index/versionUpgrade', {'downloadUrl': durl,'versionName': newVersionName,'isForceUpdate': isForceUpdate,'versionDesc': res.updateRecord,'platForm': platform})}})});
}
创建页面versionUpgrade.vue,粘贴以下内容:
<template><view class="upgrade-popup"><image class="header-bg" src="../../static/upgrade_bg.png" mode="widthFix"></image><i v-if="!isForceUpdate && isStartDownload" class="cuIcon-close close-btn" @click="handleClose"></i><view class="main"><view class="version">发现新版本{{versionName}}</view><view class="content"><text class="title">更新内容</text><view class="desc" v-html="versionDesc"></view></view><!--下载状态-进度条显示 --><view class="footer" v-if="isStartDownload"><view class="progress-view" :class="{'active':!hasProgress}" @click="handleInstallApp"><!-- 进度条 --><view v-if="hasProgress" style="height: 100%;"><view class="txt">{{percentText}}</view><view class="progress" :style="setProStyle"></view></view><view v-else><view class="btn upgrade force">{{ isDownloadFinish ? '立即安装' :'下载中...'}}</view></view></view></view><!-- 强制更新 --><view class="footer" v-else-if="isForceUpdate"><view class="btn upgrade force" @click="handleUpgrade">立即更新</view></view><!-- 可选择更新 --><view class="footer" v-else><view class="btn close" @click="handleClose">以后再说</view><view class="btn upgrade" @click="handleUpgrade">立即更新</view></view></view></view>
</template><script>import {downloadApp,installApp} from './versionUpgrade.js'import {cndUrl} from '../../api/api.js'export default {data() {return {platForm: null,isForceUpdate: false, //是否强制更新versionName: '', //版本名称versionDesc: '', //更新说明downloadUrl: '', //APP下载链接isDownloadFinish: false, //是否下载完成hasProgress: false, //是否能显示进度条currentPercent: 0, //当前下载百分比isStartDownload: false, //是否开始下载fileName: '', //下载后app本地路径名称}},computed: {//设置进度条样式,实时更新进度位置setProStyle() {return {width: (510 * this.currentPercent / 100) + 'rpx' //510:按钮进度条宽度}},//百分比文字percentText() {let percent = this.currentPercent;if (typeof percent !== 'number' || isNaN(percent)) return '下载中...'if (percent < 100) return `下载中${percent}%`return '立即安装'}},onLoad(op) {let data = JSON.parse(op.data)this.platForm = data.platFormthis.versionName = data.versionName; //版本名称this.versionDesc = data.versionDesc; //更新说明this.downloadUrl = data.downloadUrl; //下载链接this.isForceUpdate = data.isForceUpdate; //是否强制更新},onBackPress(options) {// 禁用返回if (options.from == 'backbutton') {return true;}},methods: {//更新handleUpgrade() {if (this.downloadUrl) {if (this.platForm != 'ios') {this.isStartDownload = truelet durl = cndUrl() + '/' + this.downloadUrl//开始下载AppdownloadApp(durl, current => {//下载进度监听this.hasProgress = truethis.currentPercent = current}).then(fileName => {//下载完成this.isDownloadFinish = truethis.fileName = fileNameif (fileName) {//自动安装Appthis.handleInstallApp()}}).catch(e => {console.log(e, 'e')})}//IOS无法在线升级提示到商店下载else {// const appId = '6476550601';// const appUrl = `https://apps.apple.com/app/id${appId}`;// uni.navigateTo({// url: `/common/webview?url=${encodeURIComponent(appUrl)}`// });uni.navigateTo({url: `/common/webview?url=${encodeURIComponent(this.downloadUrl)}`});}} else {uni.showToast({title: '下载链接不存在',icon: 'none'})}},//安装apphandleInstallApp() {//下载完成才能安装,防止下载过程中点击if (this.isDownloadFinish && this.fileName) {installApp(this.fileName, () => {//安装成功,关闭升级弹窗uni.navigateBack()})}},//关闭返回handleClose() {uni.navigateBack()},}}
</script><style>page {background-color: transparent;background: rgba(0, 0, 0, 0.5);/**设置窗口背景半透明*/}
</style>
<style lang="scss" scoped>.upgrade-popup {width: 580rpx;height: auto;position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);background: #fff;border-radius: 20rpx;box-sizing: border-box;border: 1px solid #eee;}.close-btn{position: absolute;right: 10rpx;font-size: 52rpx;color: gray;}.header-bg {width: 100%;margin-top: -112rpx;}.main {padding: 10rpx 30rpx 30rpx;box-sizing: border-box;.version {font-size: 36rpx;color: #026DF7;font-weight: 700;width: 100%;text-align: center;overflow: hidden;text-overflow: ellipsis;white-space: nowrap;letter-spacing: 1px;}.content {margin-top: 60rpx;.title {font-size: 28rpx;font-weight: 700;color: #000000;}.desc {box-sizing: border-box;margin-top: 20rpx;font-size: 28rpx;color: #6A6A6A;max-height: 80vh;overflow-y: auto;}}.footer {width: 100%;display: flex;justify-content: center;align-items: center;position: relative;flex-shrink: 0;margin-top: 100rpx;.btn {width: 246rpx;display: flex;justify-content: center;align-items: center;position: relative;z-index: 999;height: 96rpx;box-sizing: border-box;font-size: 32rpx;border-radius: 10rpx;letter-spacing: 2rpx;&.force {width: 500rpx;}&.close {border: 1px solid #E0E0E0;margin-right: 25rpx;color: #000;}&.upgrade {background-color: #026DF7;color: white;}}.progress-view {width: 510rpx;height: 90rpx;display: flex;position: relative;align-items: center;border-radius: 6rpx;background-color: #dcdcdc;display: flex;justify-content: flex-start;padding: 0px;box-sizing: border-box;border: none;overflow: hidden;&.active {background-color: #026DF7;}.progress {height: 100%;background-color: #026DF7;padding: 0px;box-sizing: border-box;border: none;border-top-left-radius: 10rpx;border-bottom-left-radius: 10rpx;}.txt {font-size: 28rpx;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);color: #fff;}}}}
</style>
创建versionUpgrade.js,与versionUpgrade.vue放在同一个目录中!将以下内容粘贴到versionUpgrade.js中!
/*** @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); //注册广播}
我使用的是这个UI,你可以用也可以换掉!