uniapp 版本检查更新

总体来说uniapp的跨平台还是很不错的,虽然里面各种坑要去踩,但是踩坑也是开发人员的必修课和成长路。

这不,今天就来研究了一下版本检查更新就踩到坑了。。。先来看看检查更新及下载、安装的实现。

先来看看页面:

从左到右依次为检查到版本更新,下载安装过程,下载完成提示安装。

来看看uniapp的代码实现:

在启动页面或者是你认为合适的页面添加以下方法并调用:

checkVersion() {
	//模拟接口获取最新版本号,版本号固定为整数
	let platform = uni.getSystemInfoSync().platform.toLocaleLowerCase() //手机平台
//根据你们的检查接口来具体书写,我们是根据包名来管理检查的
	let pname = null
	if (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.url
			let 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.platForm
			this.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 = true
						let durl = cndUrl() + '/' + this.downloadUrl
						//开始下载App
						downloadApp(durl, current => {
							//下载进度监听
							this.hasProgress = true
							this.currentPercent = current

						}).then(fileName => {
							//下载完成
							this.isDownloadFinish = true
							this.fileName = fileName
							if (fileName) {
								//自动安装App
								this.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'
					})
				}

			},
			//安装app
			handleInstallApp() {
				//下载完成才能安装,防止下载过程中点击
				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,你可以用也可以换掉!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/613257.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

了解 条码工具 Dynamsoft 在条码读取器中的形态运算

在图像处理中&#xff0c;术语形态学是指分析形状以填充小孔、去除噪声、提取轮廓等的一组操作。形态学操作很像空间卷积中的过滤过程。有两个部分在起作用&#xff1a;结构元素和预定义的计算规则。 点击下载Dynamsoft最新版https://www.evget.com/product/3691/download 结…

块元素、内联元素、行内块元素

一、介绍&#xff1a; CSS元素划分成块元素、行内元素&#xff08;内联元素&#xff09;、行内块元素等多种常用类型。也就是说&#xff1a;在CSS中&#xff0c;元素根据其在页面上的布局方式被分为不同的显示类型。 背景&#xff1a;HTML负责定义网页的结构和内容&#xff0c…

YOLO系列笔记(十四)——Compute Canada计算平台及其常见命令介绍

Compute Canada平台及其常见命令介绍 前言优势使用方法1. 检查模块不带版本号带版本号 2. 加载模块3. 检查模块是否加载成功4. 创建虚拟环境5. 编写作业脚本6. 提交作业7. 监控作业状态8. 查看作业开始预计时间9. 查看作业的详细输出10. 取消作业 注意结语 前言 大家好&#x…

hypack如何采集多波束数据?(上)

多波束设备有3种&#xff1a;多波束阵列&#xff0c;比如Seabat T50P&#xff1b;相干声纳&#xff0c;比如EdgeTeck 6205&#xff1b;多个单波束并列&#xff0c;比如Ross Sweep System&#xff0c;见下图。 辅助传感器主要有&#xff1a;罗经&#xff08;提供航向&#xff09…

[C++核心编程-07]----C++类和对象之友元应用

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

轻量级开源即时通讯项目:Open Im Server

Open Im Server&#xff1a;轻松搭建&#xff0c;随心沟通&#xff0c;让距离更近一步&#xff01;- 精选真开源&#xff0c;释放新价值。 概览 Open IM Server 是一个基于 Go 实现的轻量级全功能开源即时通讯服务器项目&#xff0c;专为需要高度定制和扩展性的应用程序设计。…

GAME101-Lecture06学习

前言 上节课主要讲的是三角形的光栅化。重要的思想是要利用像素的中心对三角形可见性的函数进行采样。 这节课主要就是反走样。 课程链接&#xff1a;Lecture 06 Rasterization 2 (Antialiasing and Z-Buffering)_哔哩哔哩_bilibili 反走样引入 ​ 通过采样&#xff0c;得到…

18 分页:介绍

目录 简单例子 页表存在哪里 列表中究竟有什么 分页&#xff1a;也很慢 内存追踪 小结 在解决大多数空间管理问题上面&#xff0c;操作系统有两种方法&#xff1a; 第一种就是将空间分割成不同长度的分片&#xff0c;类似于虚拟内存管理中的分段&#xff0c;但是这个方法…

【redis】Redis五种常用数据类型和内部编码,以及对String字符串类型的总结

˃͈꒵˂͈꒱ write in front ꒰˃͈꒵˂͈꒱ ʕ̯•͡˔•̯᷅ʔ大家好&#xff0c;我是xiaoxie.希望你看完之后,有不足之处请多多谅解&#xff0c;让我们一起共同进步૮₍❀ᴗ͈ . ᴗ͈ აxiaoxieʕ̯•͡˔•̯᷅ʔ—CSDN博客 本文由xiaoxieʕ̯•͡˔•̯᷅ʔ 原创 CSDN 如…

设计模式 六大原则之单一职责原则

文章目录 概述代码例子小结 概述 先看下定义吧&#xff0c;如下&#xff1a; 单一职责原则的定义描述非常简单&#xff0c;也不难理解。一个类只负责完成一个职责或者功能。也就是说在类的设计中&#xff0c; 我们不要设计大而全的类,而是要设计粒度小、功能单一的类。 代码例…

提高Rust安装与更新的速度

一、背景 因为rust安装过程中&#xff0c;默认的下载服务器为crates.io&#xff0c;这是一个国外的服务器&#xff0c;国内用户使用时&#xff0c;下载与更新的速度非常慢&#xff0c;因此&#xff0c;我们需要使用一个国内的服务器来提高下载与更新的速度。 本文推荐使用字节…

AI大模型探索之路-训练篇15:大语言模型预训练之全量参数微调

系列篇章&#x1f4a5; AI大模型探索之路-训练篇1&#xff1a;大语言模型微调基础认知 AI大模型探索之路-训练篇2&#xff1a;大语言模型预训练基础认知 AI大模型探索之路-训练篇3&#xff1a;大语言模型全景解读 AI大模型探索之路-训练篇4&#xff1a;大语言模型训练数据集概…

Linux 安裝 rpm包

下载 地址&#xff1a;https://developer.aliyun.com/packageSearch 安装 rpm -ivh lsof-4.87-6.el7.x86_64.rpmlsof -Ki|awk {print $2}|sort|uniq -c|sort -nr|head lsof | wc -l

读天才与算法:人脑与AI的数学思维笔记24_预测性文本生成器

1. 起源 1.1. 人类讲故事可能起源于“假如……”这种问答结构 1.2. 讲故事是人类做安全试验的一种方式 1.2.1. 如果你问一个人“假如……”&#xff0c;其实是在探索你的行为对他可能带来的影响 1.3. 最早出现的故事极有可能就源自我们对在周遭混乱的环境中寻找某种秩序的渴…

06_图(Graph)

图的定义 图&#xff08;Graph&#xff09;是由顶点的有穷非空集合和顶点之间的集合组成&#xff0c;通常表示为&#xff1a;G(V,E)&#xff0c;其中&#xff0c;G表示一个图&#xff0c;V是图G中顶点集合&#xff0c;E是图G中边的集合。 对于图的定义&#xff0c;需要注意的地…

矩阵和空间变换理解

矩阵和空间变换 把向量和矩阵相乘看作是空间变换&#xff0c;是其中一种看法 代数角度&#xff1a;向量的一行和矩阵的一列逐项相乘再相加等于新向量的一项 w代表原来坐标轴和新坐标轴之间的变换关系&#xff0c;而a和b体现的是原来向量的关系 矩阵代表的是旧坐标和新坐标之间…

Redis 实战之命令请求的执行过程

命令请求的执行过程 发送命令请求读取命令请求命令执行器&#xff08;1&#xff09;&#xff1a;查找命令实现命令执行器&#xff08;2&#xff09;&#xff1a;执行预备操作命令执行器&#xff08;3&#xff09;&#xff1a;调用命令的实现函数命令执行器&#xff08;4&#x…

深入了解 PCIe 6.0 的演变和优化

PCI-Express是继ISA和PCI总线之后的第三代I/O总线&#xff0c;即3GIO。由Intel在2001年的IDF上提出&#xff0c;后来PCI-SIG&#xff08;PCI特殊兴趣组织&#xff09;认证发布后才改名为“PCI-Express”。它的主要优势就是数据传输速率高&#xff0c;另外还有抗干扰能力强&…

Python 日志模块Loguru基本使用和封装使用

【一】介绍 Loguru是一个用于Python的日志库&#xff0c;它的设计目标是使日志记录变得简单、快速且易于阅读。 &#xff08;1&#xff09;Loguru介绍 简洁的API&#xff1a;Loguru提供了一个简洁的API&#xff0c;使得在Python项目中使用日志变得更加容易。只需导入loguru模…

flac和mp3的区别是什么?答案在这里

在数字音乐时代&#xff0c;音频格式的选择对于音质和文件大小的影响至关重要。FLAC和MP3是两种常见的音频格式&#xff0c;它们在音质和压缩方式上存在明显的差异。了解flac和mp3的区别&#xff0c;有助于我们在不同的场景下选择合适的音频格式&#xff0c;以获得最佳的音乐体…