uniapp 版本检查更新

news2024/12/27 13:39:05

总体来说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,你可以用也可以换掉!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux系统编程】第十六弹---冯诺依曼体系结构与操作系统

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】【C详解】【Linux系统编程】 目录 1、冯诺依曼体系结构 2、操作系统原理 2.1、什么是操作系统&#xff1f; 2.2、用图解释操作系统 2.3、理解操作系统 总结 …

瞪羚企业申报条件!武汉市瞪羚企业奖励补助

武汉市江岸区、江汉区、硚口区、汉阳区、武昌区、青山区、洪山区、蔡甸区、江夏区、黄陂区、新洲区、东西湖区、汉南区企业申报瞪羚企业的条件是什么&#xff1f;各区对瞪羚企业的奖励补助有哪些&#xff1f; 武汉市瞪羚企业申报条件&#xff1a; 1、符合武汉市光电子信息、生物…

Windows Server 2012 R2 新增D盘分区

我们经常搭建windows版本的游戏时会要在D盘上操作&#xff0c;今天就介绍下新的服务器如何新增一个D盘。 在"开始"图标右边有个”服务器管理器“&#xff0c;单击点开 点开服务器管理器后&#xff0c;点击“工具”打开“计算机管理” 打开计算机管理后点击“存储”-…

发票审核如何自查?报销没有发票,如何处理?

在财务管理中&#xff0c;发票是非常重要的一项凭证&#xff0c;是费用核算和税务申报的重要依据&#xff0c;但光靠发票入账可能会被定义为虚开。 一、费用报销审核必看的6个要点 1、票据与实际业务吻合 这是费用报销中最基本的常识&#xff0c;比如&#xff1a;采购一批物料&…

T型三电平逆变器的Simulink仿真

1 T型三电平拓扑的开关状态 图1为T字型-三电平电路单相拓扑&#xff0c;拓扑中共有4个IGBT&#xff0c;4个二极管&#xff0c;还有电容组C1和C2&#xff1b;假设正负母线电压均等&#xff0c;都是Vdc。将T1&#xff0c;T2&#xff0c;T3&#xff0c;T4的状态用1和0分别表示&…

51单片机入门:串口通信

串行通信的初步认识 通信方式分类 1、按照数据传送方式&#xff1a; 并行通信&#xff1a;通信时数据的各个位同时传送&#xff0c;可以实现字节为单位的通信。 但是通信线多&#xff0c;占用资源多&#xff0c;成本高。 串行通信&#xff1a;一次只能发送一位&#xff0c…

Linux:进程概念(三.详解进程:进程状态、优先级、进程切换与调度)

上次讲了进程这些内容&#xff1a;Linux&#xff1a;进程概念&#xff08;二.查看进程、父进程与子进程、进程状态详解&#xff09; 文章目录 1.Linux中的进程状态1.1前台进程和后台进程运行状态睡眠状态磁盘休眠状态停止状态kill指令—向进程发送信号 死亡状态 2.僵尸进程2.1僵…

零售全渠道营销业务链分析,让企业管控能力大幅加强!

对于传统的、规模化的零售快消企业来讲&#xff0c;面临着很大的渠道管理和建设问题&#xff0c;如何尽快实现整个营销体系的全渠道数字化转型是当务之急、重中之重。 面对错综分散的经销商&#xff0c;零售快消企业订货流程会越复杂&#xff0c;加之对门店管理较为粗放&#…

武汉星起航:亚马逊母亲节选品指南,热销产品助卖家赢取节日商机

随着母亲节的脚步日益临近&#xff0c;全球消费者纷纷开始为这一特殊的节日挑选礼物&#xff0c;以表达对母亲的深深感激和无尽爱意。作为跨境电商的重要平台&#xff0c;亚马逊凭借其丰富的商品种类和便捷的购物体验&#xff0c;成为消费者选购母亲节礼物的首选之地。那么&…

【数据结构陈越版笔记】第1章 概论

我最近准备以陈姥姥的数据结构教材为蓝本重新学一下数据结构&#xff0c;写一下读书笔记 第1章 概论 1.1 引子 概论中首先描述了&#xff0c;数据结构的定义没有具体的定义&#xff0c;初学者可以不用管这个定义的问题&#xff0c;但是我理解的和维基百科的说法是一样的“数…

[已解决]ModuleNotFoundError: No module named ‘tqdm‘

&#x1f60e; 作者介绍&#xff1a;我是程序员行者孙&#xff0c;一个热爱分享技术的制能工人。计算机本硕&#xff0c;人工制能研究生。公众号&#xff1a;AI Sun&#xff0c;视频号&#xff1a;AI-行者Sun &#x1f388; 本文专栏&#xff1a;本文收录于《AI实战中的各种bug…

如何批量删除多个不同路径的文件但又保留文件夹呢

首先&#xff0c;需要用到的这个工具&#xff1a; 度娘网盘 提取码&#xff1a;qwu2 蓝奏云 提取码&#xff1a;2r1z 1、我准备了三个文件夹&#xff08;实际操作的时候可能是上百个文件夹&#xff0c;无所谓&#xff09;&#xff0c;里面都放了两个图片 2、然后打开工具&am…

RustDesk 自建服务器部署和使用教程

RustDesk 是一个强大的开源远程桌面软件&#xff0c;是中国开发者的作品&#xff0c;它使用 Rust 编程语言构建&#xff0c;提供安全、高效、跨平台的远程访问体验。可以说是目前全球最火的开源远程桌面软件了&#xff0c;GitHub 星星数量达到了惊人的 64k&#xff01; 与 Team…

AIGC|将GPTBots与10000+主流软件连接,实现应用场景全覆盖

一、自动化工作流的无限可能&#xff0c;由AI带来 当前市场上存在许多自动化工作流工具&#xff0c;这些工具在很大程度上提升了人们的工作效率&#xff0c;为企业节省了大量时间和人力成本。然而&#xff0c;这些工具并非万能&#xff0c;它们在实际应用中仍存在一定的局限性…

如何在自己的服务器上快速搭建第一个网站(其一)

根据上篇文章相信很多人以及成功搭建服务器啦。今天我们讲下如何在自己的服务器快速搭建第一个网站的一些重要配置&#xff0c;以及搭建网站的必备环境。干货满满&#xff0c;希望大家能够关注点赞收藏。 我会不定期更新一些实用的工具&#xff0c;欢迎大家私信评论喔&#xf…

工作中使用Optional处理空指针异常

工作中使用Optional处理空指针异常 实体类以前对空指针的判断Optional处理空指针测试结果 实体类 package po;import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor;import java.io.Serializable;Data AllArgsConstructor NoArgsConstruct…

kafka生产者消费者举例

文章目录 kafka介绍生产者消费者例子一、生产者二、消费者三、效果 KafkaTemplate KafkaListener kafka介绍 Kafka 是一款分布式流处理平台&#xff0c;它被设计用于高吞吐量、持久性、分布式的数据流处理。 Kafka 简介&#xff1a; Kafka 是一个高吞吐、分布式、基于发布 订阅…

NSS刷题

[SWPUCTF 2021 新生赛]jicao 类型&#xff1a;PHP、代码审计、RCE 主要知识点&#xff1a;json_decode()函数 json_decode()&#xff1a;对JSON字符串解码&#xff0c;转换为php变量 用法&#xff1a; <?php $json {"ctf":"web","question"…

2024年数维杯B题完整代码和思路论文讲解与分析

2024数维杯数学建模完整代码和成品论文已更新&#xff0c;获取↓↓↓↓↓ https://www.yuque.com/u42168770/qv6z0d/bgic2nbxs2h41pvt?singleDoc# 2024数维杯数学建模B题45页论文和代码已完成&#xff0c;代码为全部问题的代码 论文包括摘要、问题重述、问题分析、模型假设、…

怎么让电脑耳机和音响都有声音

电脑耳机音响不能同时用没声音怎么办 一般来说&#xff0c;重新开机后问题能够得到解决。右击“我的电脑”---“属性”---“硬件”---“设备管理器”&#xff0c;打开“声音、视频和游戏控制器”有无问题&#xff0c;即看前面有没有出现黄色的“”。 如果您的 电脑 耳机能正常…