uniapp实现app检查更新与升级-uni-upgrade-center详解

news2024/11/18 10:51:12

app检查更新与升级

参考链接:

升级中心uni-upgrade-center - App

uni-admin

h5+ api

App资源在线升级更新

uni-app使用plus注意事项

关于在线升级(WGT)的几个疑问

什么是升级中心uni-upgrade-center

uniapp官方开发的App版本更新的插件,基于unicloud的后端服务

因为是开源的,通过修改源码可以实现请求java等其他后端服务,后续的源码解析章节会介绍

升级中心分为两个部分:

前台检测更新: uni-upgrade-center-app

后台管理系统:

  • uni-admin >= 1.9.3 :uni-admin 已内置 升级中心,直接使用即可。并且云函数 upgrade-center 废弃,使用 uni-upgrade-center 云函数。
  • uni-upgrade-center Admin管理后台 (uni-admin 1.9.3+ 已内置,此插件不再维护)
    • 1.9.0 <= uni-admin < 1.9.2 :请前往 Gitee 下载 tag v0.5.1 版本使用
    • uni-admin < 1.9.0:请前往 Gitee 下载 tag v0.4.2 版本使用

简单来说,如果是新版的uni-admin,直接用升级中心即可

怎么使用uni-upgrade-center

使用我觉得并不难,跟着官方文档走即可

简单来说,就是你的app项目安装 uni-upgrade-center-app这个插件,同时你需要另外新建一个uni-admin项目,用来上传并管理app项目的更新包,app项目通过unicloud请求更新包

官方文档

但是如果不想使用unicloud,想换成java等其他后端服务,或者想了解app检查更新与升级的代码是如何编写的,阅读uni-upgrade-center源码是十分有必要的。

uni-upgrade-center源码阅读

十分推荐阅读uni-upgrade-center源码

通过一步步阅读uni-upgrade-center源码,基本能完全学会如何写app检查更新与升级的代码

源码前端功能实现主要分为三个文件,依次阅读

  1. utils/call-check-version.js
  2. utils/call-check-version.js
  3. pages/upgrade-popup.vue

utils/call-check-version.js

代码很简单,通过h5+ api获取应用信息,把应用信息传递给uniCloud云函数

同理,如果不使用云函数,传给java等后端服务的话,替换云函数部分代码就可以了

export default function () {
  // #ifdef APP-PLUS
  return new Promise((resolve, reject) => {
    // 根据当前应用的appid,获取appid对应的应用信息
    plus.runtime.getProperty(plus.runtime.appid, function (widgetInfo) {
      const data = {
        action: 'checkVersion',
        appid: plus.runtime.appid,
        appVersion: plus.runtime.version,
        wgtVersion: widgetInfo.version
      }
      console.log("data: ", data);
      // 如果传给java等后端服务,改下方代码
      uniCloud.callFunction({
        name: 'uni-upgrade-center',
        data,
        success: (e) => {
          console.log("e: ", e);
          resolve(e)
        },
        fail: (error) => {
          reject(error)
        }
      })
    })
  })
  // #endif
  // #ifndef APP-PLUS
  return new Promise((resolve, reject) => {
    reject({
      message: '请在App中使用'
    })
  })
  // #endif
}

plus.runtime.appid

当前应用的APPID

String 类型 只读属性

注意,如果是在HBuilder真机运行获取的是固定值"HBuilder",需要提交App云端打包后运行才能获取真实的APPID值

plus.runtime.getProperty

获取指定APPID对应的应用信息

参数:

  • appid: ( String ) 必选 应用的Appid
  • getPropertyCB: ( GetPropertyCallBack ) 必选 获得应用信息成功回调函数

示例:

// 获取应用信息
function getAppInfo() {
	plus.runtime.getProperty( plus.runtime.appid, function ( wgtinfo ) {
		//appid属性
		var wgtStr = "appid:"+wgtinfo.appid;
		//version属性
		wgtStr += "<br/>version:"+wgtinfo.version;
		//name属性
		wgtStr += "<br/>name:"+wgtinfo.name;
		//description属性
		wgtStr += "<br/>description:"+wgtinfo.description;
		//author属性
		wgtStr += "<br/>author:"+wgtinfo.author;
		//email属性
		wgtStr += "<br/>email:"+wgtinfo.email;
		//features 属性
		wgtStr += "<br/>features:"+wgtinfo.features;
		console.log( wgtStr );
	} );
}

utils/call-check-version.js

官方实现了两种方式,静默更新和提示更新

import callCheckVersion from './call-check-version'

// 推荐在App.vue中使用
const PACKAGE_INFO_KEY = '__package_info__'

export default function() {
	// #ifdef APP-PLUS
	return new Promise((resolve, reject) => {
		callCheckVersion().then(async (e) => {
			if (!e.result) return;
			const {
				code,
				message,
				is_silently, // 是否静默更新
				url, // 安装包下载地址
				platform, // 安装包平台
				type // 安装包类型
			} = e.result;

			// 此处逻辑仅为实例,可自行编写
			if (code > 0) {
				// 腾讯云和阿里云下载链接不同,需要处理一下,阿里云会原样返回
				const {
					fileList
				} = await uniCloud.getTempFileURL({
					fileList: [url]
				});
				if (fileList[0].tempFileURL)
					e.result.url = fileList[0].tempFileURL;

				resolve(e)

				// 静默更新,只有wgt有
				if (is_silently) {
					uni.downloadFile({
						url: e.result.url,
						success: res => {
							if (res.statusCode == 200) {
								// 下载好直接安装,下次启动生效
								plus.runtime.install(res.tempFilePath, {
									force: false
								});
							}
						}
					});
					return;
				}

				/**
				 * 提示升级一
				 * 使用 uni.showModal
				 */
				// return updateUseModal(e.result)

				/**
				 * 提示升级二
				 * 官方适配的升级弹窗,可自行替换资源适配UI风格
				 */
				uni.setStorageSync(PACKAGE_INFO_KEY, e.result)
				uni.navigateTo({
					url: `/uni_modules/uni-upgrade-center-app/pages/upgrade-popup?local_storage_key=${PACKAGE_INFO_KEY}`,
					fail: (err) => {
						console.error('更新弹框跳转失败', err)
						uni.removeStorageSync(PACKAGE_INFO_KEY)
					}
				})
				
				return
			} else if (code < 0) {
				// TODO 云函数报错处理
				console.error(message)
				return reject(e)
			}
			return resolve(e)
		}).catch(err => {
			// TODO 云函数报错处理
			console.error(err.message)
			reject(err)
		})
	});
	// #endif
}

/**
 * 使用 uni.showModal 升级
 */
function updateUseModal(packageInfo) {
	const {
		title, // 标题
		contents, // 升级内容
		is_mandatory, // 是否强制更新
		url, // 安装包下载地址
		platform, // 安装包平台
		type // 安装包类型
	} = packageInfo;

	let isWGT = type === 'wgt'
	let isiOS = !isWGT ? platform.includes('iOS') : false;
	let confirmText = isiOS ? '立即跳转更新' : '立即下载更新'

	return uni.showModal({
		title,
		content: contents,
		showCancel: !is_mandatory,
		confirmText,
		success: res => {
			if (res.cancel) return;

			// 安装包下载
			if (isiOS) {
				plus.runtime.openURL(url);
				return;
			}

			uni.showToast({
				title: '后台下载中……',
				duration: 1000
			});

			// wgt 和 安卓下载更新
			downloadTask = uni.downloadFile({
				url,
				success: res => {
					if (res.statusCode !== 200) {
						console.error('下载安装包失败', err);
						return;
					}
					// 下载好直接安装,下次启动生效
					plus.runtime.install(res.tempFilePath, {
						force: false
					}, () => {
						if (is_mandatory) {
							//更新完重启app
							plus.runtime.restart();
							return;
						}
						uni.showModal({
							title: '安装成功是否重启?',
							success: res => {
								if (res.confirm) {
									//更新完重启app
									plus.runtime.restart();
								}
							}
						});
					}, err => {
						uni.showModal({
							title: '更新失败',
							content: err
								.message,
							showCancel: false
						});
					});
				}
			});
		}
	});
}

静默更新

可以看出静默更新分为三步:

  1. 后端提供一个下载更新包的url
  2. 前端uni.downloadFile该url地址
  3. 下载好后前端调用plus.runtime.install安装更新包
// 静默更新,只有wgt有
			if (is_silently) {
				uni.downloadFile({
					url: e.result.url,
					success: res => {
						if (res.statusCode == 200) {
							// 下载好直接安装,下次启动生效
							plus.runtime.install(res.tempFilePath, {
								force: false
							});
						}
					}
				});
				return;
			}

强制更新

首先,我们需要知道的是,plus.runtime.install成功后就已经安装完更新包了,用户下次打开app就会是最新版的app,这里强制更新的意思是是否立刻重启app,强制用户立刻使用最新版app

plus.runtime.install后有三种应用场景,这里官方写的很好,三种场景都处理了:

  1. 不征求客户意见,直接重启app,强制用户立刻使用最新版
  2. 征求客户意见,如果重启,用户使用最新版,如果不重启,等用户下次打开app显示最新版
  3. 不重启,等用户下次打开app显示最新版
			    // 安装下载的安装包,下次启动生效
					plus.runtime.install(res.tempFilePath, {
						force: false
					}, () => {
            // is_mandatory是后端返回的控制是否强制更新的变量
            // 强制更新就是强制重启app,否则就是用户下次打开app才会更新
            // 强制更新体验不好,还是下次打开更新会好很多
						if (is_mandatory) {
							// 更新完重启app
							plus.runtime.restart();
							return;
						}
						uni.showModal({
							title: '安装成功是否重启?',
							success: res => {
								if (res.confirm) {
									// 更新完重启app
									plus.runtime.restart();
								}
							}
						});
					}, err => {
						uni.showModal({
							title: '更新失败',
							content: err
								.message,
							showCancel: false
						});
					});

跳转应用商店

  1. 后端返回安装包平台和安装包类型
  2. 安装包类型是否是wgt,如果不是,判断安装包平台是否包含iOS,调用第三方程序打开url安装iOS更新包,iOS是跳转更新,其他是下载更新
  3. ios需要上架、通过市场安装,所以需要第三方程序打开url

plus.runtime.openURL表示调用第三方程序打开url进行安装,即跳转应用商店功能

function updateUseModal(packageInfo) {
	const {
		title, // 标题
		contents, // 升级内容
		is_mandatory, // 是否强制更新
		url, // 安装包下载地址
		platform, // 安装包平台
		type // 安装包类型
	} = packageInfo;

	let isWGT = type === 'wgt'
	let isiOS = !isWGT ? platform.includes('iOS') : false;
	let confirmText = isiOS ? '立即跳转更新' : '立即下载更新'

	return uni.showModal({
		title,
		content: contents,
		showCancel: !is_mandatory,
		confirmText,
		success: res => {
			if (res.cancel) return;

			// 安装包下载
			if (isiOS) {
				plus.runtime.openURL(url);
				return;
			}
      ...
		}
	});
}

用户取消下载

https://uniapp.dcloud.net.cn/api/request/network-file.html#downloadfile

var downloadTask = uni.downloadFile({
	url: 'https://www.example.com/file/test', //仅为示例,并非真实接口地址。
	complete: ()=> {}
});
downloadTask.abort();

如何打包wgt资源包

一、更改项目manifest.json中的应用版本名称与应用版本号

请添加图片描述
二、HBuilderX>发行>原生App-制作应用wgt包>确定
请添加图片描述
请添加图片描述
三、开发测试的时候,记得再改回原先的应用版本名称与应用版本号,不然版本跟线上的相同,安装更新包的时候就会出现WGT安装包中manifest.json文件的version版本不匹配,本地测试不了更新效果

如何查看wgt文件manifest.json

wgt包生成后会是.wgt后缀名,更改其后缀名为.zip,再解压,就可以查看manifest.json

报错解决:WGT安装包中manifest.json文件的version版本不匹配

manifest.json中的版本大于等于了线上的版本,自行排查即可

通过uni-admin上传wgt资源包

请添加图片描述

uni-admin报错解决:超级管理员已存在

是因为admin账户是旧的,跟appid对不上,删除旧的admin账户,重新创建

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

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

相关文章

结构体的不定长数组,用起来就是这么爽

结构体的不定长数组 结构体数组不定长的做法&#xff0c;有两种 第一种&#xff1a; 指针 第二种&#xff1a;长度为0的数组 1. 结构体的数组指针 特点&#xff1a; 结构体初始化时&#xff0c;可以是结构体指针&#xff0c;如struct tag_info *pInfo NULL; 也可以是结构体变量…

Python文件和数据格式化(教程)

文件是一个存储在副主存储器的数据序列&#xff0c;可包含任何数据内容。 概念上&#xff0c;文件是数据的集合和抽象&#xff0c;类似的&#xff0c;函数是程序的集合和抽象。 用文件形式组织和表达数据更有效也更加灵活。 文件包括两种形式&#xff0c;文本文件和二进制文…

推荐几款市面上常用的免费CMS建站系统

小编在网站建设行业从业十几年&#xff0c;很多客户或者朋友找我做网站的时候&#xff0c;都喜欢开发一个完全熟悉自己的网站系统&#xff0c;但是小编这里很不推荐。从0到1全新开发&#xff0c;成本&#xff0c;效率和成熟度这些和主流的cms建站系统比起来&#xff0c;完全没有…

文件与IO

一.文件的定义什么是文件&#xff1f;文件分为狭义上的文件和广义上的文件 狭义上的文件&#xff1a;文件夹中的文件&#xff1a;包括视频、图片、文本、可执行文件等等......其中有些文件是有后缀名的&#xff0c;而有一些文件是没有后缀名的广义上的文件&#xff1a;在Linux系…

Unix Linux、MAC、Window 如何安装配置环境?都在这里啦~

嗨害大家好鸭&#xff01;我是小熊猫~ 这次将向大家介绍如何在本地搭建Python开发环境。 Python可应用于多平台包括 Linux 和 Mac OS X。 你可以通过终端窗口输入 “python” 命令来查看本地是否已经安装Python以及Python的安装版本。 源码资料电子书:点击此处跳转文末名片获…

PHP代码审计神器——RIPS个人汉化版(2017年老文)

一、RIPS简介 RIPS是一款PHP开发的开源的PHP代码审计工具&#xff0c;由国外的安全研究者Johannes Dahse开发&#xff0c;目前开源的最新版本是0.55。 程序小巧玲珑&#xff0c;仅有不到500kb&#xff0c;其中的PHP语法分析非常精准&#xff0c;可以实现跨文件变量和函数追踪…

Virtualbox安装Windows11教程,提供虚机专用镜像下载。

微软在Windows11安装过程中增加了TPM2.0安全验证&#xff0c;所以一些老旧的电脑或者不带TPM认证协议的虚拟机都无法安装系统镜像。 这给我们体验尝鲜带来了一些小小的困扰。其实有2种解决方法可以在虚拟机中体验到Windows11带来的变化。 方法一 虚拟机启动时先加载PE系统镜…

Python 版本的常见算法模板(一)

文章目录前言排序模板排序算法归并排序KMP图邻接表Floyd 算法DijkstraBellMan-Ford 算法SPFA 算法Prim 算法Kruskra 算法染色法Hunger算法前言 翻了翻自己以前写的一些博文&#xff0c;发现的话&#xff0c;还是有一些误区没有写好的&#xff0c;所以的话这里的重新写一下&…

年薪40W的测试工程师被裁,回怼的一番话,令人沉思...

腾讯一位测试工程师被炒&#xff0c;回怼到:“反正我有技术&#xff0c;在哪不一样” 在腾讯上班的朋友给我分享了今天在他公司遇到的事情&#xff0c;他部门一位测试工程师被炒&#xff0c;具体原因好像就是跟上司闹矛盾&#xff0c;部门的都觉得非常可惜&#xff0c;因为他算…

本地修改的文件,使用git stash暂存之后不小心将暂存区清空,重新找回之前被暂存的文件

概述 问题 日常使用git 时&#xff0c;将本地所做的修改使用git stash暂存&#xff0c;使用git pull拉取代码之后&#xff0c;之间用git stash clear将git stash暂存的内容删除掉了。本文讲述如何恢复git stash clear掉的暂存区代码。 解决方法 执行指令 git log --graph -…

银行存取款程序设计(JAVA基础案例教程-黑马程序员编著-第三章-课后作业)

【案例3-2】银行存取款程序设计 【案例介绍】 案例描述 银行存取款的流程是人们非常熟悉的事情&#xff0c;用户可在银行对自己的资金账户进行存款、取款、查询余额等操作&#xff0c;极大的便利了人民群众对资金的管理。 本任务要求&#xff0c;使用所学知识编写一个银行存…

spring项目中使用策略模式

小白看了Java设计模式一书&#xff0c;晕晕乎乎&#xff0c;好像懂了&#xff0c;又好像啥都没懂。对照着书本一行行手打代码&#xff0c;完毕&#xff0c;执行&#xff0c;ok&#xff0c;设计模式已掌握。但到了项目中却又茫然。 小白我啊&#xff0c;今天尝试一下在自己的dem…

【思科设备,最常用的命令是下面这些吗!】

​在调试思科设备时&#xff0c;我们会经常使用各种命令去实现&#xff0c;但是使用最为频繁的有哪些&#xff1f;我们来看看下面频繁出现但是又非常有用且常用的命令&#xff01; 1、&#xff1f; 在使用命令行时&#xff0c;我们不可能记住所有的命令&#xff0c;有时候只能…

git的一些常用指令

1&#xff09;拷贝一个 Git 仓库到本地&#xff0c;让自己能够查看该项目&#xff0c;或者进行修改。 git clone 远程git仓库地址2&#xff09;初始化本地git仓库。 git init 3&#xff09;监控工作区的状态树&#xff0c;会把工作时的所有变化提交到暂存区&#xff0c;这里…

(七)、首页列表数据渲染【uniapp+uinicloud多用户社区博客实战项目(完整开发文档-从零到完整项目)】

1&#xff0c;获取首页列表数据 1.1在index页面中编写从数据库中获取首页列表数据的方法 //获取首页列表数据getData() {let artTemp db.collection("quanzi_articles").getTemp();let userTemp db.collection("uni-id-users").field("_id,usernam…

智慧校园人脸识别系统源码

智慧校园人脸识别系统源码 技术架构&#xff1a; 后端&#xff1a;Java 框架&#xff1a;springboot 前端页面&#xff1a;vue element-ui 小程序&#xff1a;小程序原生开发 电子班牌&#xff1a;Java Android 源码有演示&#xff0c;可正常上线运营可授权。 随着智慧校…

在成都的哪个培训机构学习Java好呢?

自从小课06年进入成都这个IT培训市场以来&#xff0c;短短十几年&#xff0c;招过很多学员&#xff0c;也见证过很多机构的起起落落。心中有万分的感慨&#xff0c;总结下来有这几点分享给大家&#xff0c;在选择培训机构时能看清本质&#xff0c;找到适合自己靠谱的机构学Java…

Go大道至简之抓取网页

目录前期准备环境教程浏览器启动命令启动Rod启动浏览器Rod自动查找浏览器路径并启动输入和点击、Enter动作多页面抓取前期准备 环境 Go版本大于等于1.18Go模块源更换&#xff0c;加速模块下载go env -w GO111MODULEon go env -w GOPROXYhttps://goproxy.cn,directRod模块 Rod…

4年经验来面试20K的测试岗,连基础都不会,还不如招应届生。

公司前段时间缺人&#xff0c;也面了不少测试&#xff0c;结果竟然没有一个合适的。一开始瞄准的就是中级的水准&#xff0c;也没指望来大牛&#xff0c;提供的薪资在10-20k&#xff0c;面试的人很多&#xff0c;但平均水平很让人失望。 看简历很多都是3、4年工作经验&#xf…

chatGPT做了这么一道数学题,我陷入了沉思

已知 2cos23cosasina−3sin2a1,并且a∈(−32π,−π)2cos^{2}3cosasina-3sin^{2}a1 ,并且a\in(-\frac{3}{2}\pi,-\pi) 2cos23cosasina−3sin2a1,并且a∈(−23​π,−π) 求 2sin(π−a)−3sin(π2a))4sina−9cosa\frac{2sin(\pi-a)-3sin(\frac{\pi}{2}a))}{4sina-9cosa} 4sina−…