导语:当一个 APP 应用开发完成以后,就要上架应用商店,但有时候修改一些小问题或者推出一些活动,又不想频繁地提交应用商店审核,那么就可以使用应用内更新功能来进行应用的版本升级更新或热更新,下面就介绍一下实现的方法。
目录
准备工作
- 在
/pages/index
文件夹下面新建一个version.vue
的组件;
- 按照前面文章所说的页面结构,编写好预定的页面;
原理分析
下面是应用更新的原理总结。
安装包版本更新
- 通过
uni.getSystemInfoSync
方法的appVersion
属性获取到应用当前安装包版本号;
- 通过请求版本更新接口获取线上的安装包版本号;
- 比较两个安装包版本号的大小,如果一致不更新,如果不一致,线上大于当前更新版本,线上小于当前不更新;
资源包版本更新
- 通过
uni.getStorage
获取本地资源包版本号,如不存在,则通过uni.setStorage
设置默认版本号;
- 通过请求版本更新接口获取线上的资源包版本号;
- 比较两个资源包版本号的大小,如果一致不更新,如果不一致,线上大于当前更新版本,线上小于当前不更新;
实战演练
模板使用
| <view class="version-box"> |
| <view class="version-item"> |
| 版本1: |
| <input |
| class="version-item-ipt" |
| type="text" |
| placeholder="请输入版本1" |
| v-model="versionInfo.v1" /> |
| </view> |
| <view class="version-item"> |
| 版本2: |
| <input |
| class="version-item-ipt" |
| type="text" |
| placeholder="请输入版本2" |
| v-model="versionInfo.v2" /> |
| </view> |
| <view class="version-item"> |
| <button class="version-item-btn" type="primary" size="mini" @click="compareVersion('test')"> |
| 比较版本 |
| </button> |
| </view> |
| <view class="version-item" v-show="versionInfo.text"> |
| <text>比较结果:</text> |
| <text class="version-item-txt">{{ versionInfo.text }}</text> |
| </view> |
| </view> |
| |
| <view class="version-box"> |
| <view class="version-item"> |
| <button class="version-item-btn" type="primary" size="mini" @click="getVersion"> |
| 获取版本 |
| </button> |
| </view> |
| <view class="version-item"> 当前版本: {{ checkInfo.current }} </view> |
| <view class="version-item"> 线上版本: {{ checkInfo.online }} </view> |
| <view class="version-item"> 当前资源包版本: {{ checkInfo.currentSource }} </view> |
| <view class="version-item"> 线上资源包版本: {{ checkInfo.onlineSource }} </view> |
| </view> |
| |
| |
| <view class="version-box"> |
| <view class="version-item"> |
| <button class="version-item-btn" type="primary" size="mini" @click="checkUpdate"> |
| 检测更新 |
| </button> |
| </view> |
| <view class="version-item" v-show="checkInfo.showProgress"> |
| <progress |
| :percent="checkInfo.currentProgress" |
| show-info |
| :stroke-width="8" |
| active-color="#24afd6" /> |
| </view> |
| </view> |
| |
样式编写
| .version-box { |
| padding: 10rpx; |
| .version-item { |
| display: flex; |
| justify-content: flex-start; |
| align-items: center; |
| margin-bottom: 20rpx; |
| padding: 0 10rpx; |
| .version-item-ipt { |
| margin-left: 20rpx; |
| padding: 10rpx; |
| border: 3rpx solid $e; |
| font-size: 27rpx; |
| } |
| .version-item-btn { |
| margin: 0; |
| } |
| .version-item-txt { |
| color: $mainColor; |
| } |
| .uni-progress { |
| width: 100%; |
| } |
| } |
| } |
脚本使用
定义数据
| const versionInfo = reactive({ |
| v1: "", |
| v2: "", |
| text: "", |
| }); |
| const checkInfo = reactive({ |
| current: "0.0.0", |
| online: "0.0.0", |
| currentSource: 0, |
| onlineSource: 0, |
| result: "", |
| data: null, |
| type: "", |
| showProgress: false, |
| currentProgress: 0, |
| downloader: null, |
| }); |
方法调用
使用之前介绍的静态服务器放置版本更新配置文件,格式如下:
| { |
| "install": { |
| "version": "1.0.0", |
| "des": "亲爱的用户:\n有新的安装包发布了\n是否更新?", |
| "url": "http://192.168.1.11:3000/xxx-1.0.0.apk" |
| }, |
| "source": { |
| "version": 1, |
| "des": "亲爱的用户:\n有新的资源包发布了\n是否更新?", |
| "url": "http://192.168.1.11:3000/xxx-001.wgt" |
| } |
| } |
| |
| |
| function compareVersion(v1, v2) { |
| v1 = v1.split("."); |
| v2 = v2.split("."); |
| let len = Math.max(v1.length, v2.length); |
| while (v1.length < len) { |
| v1.push("0"); |
| } |
| while (v2.length < len) { |
| v2.push("0"); |
| } |
| |
| for (let i = 0; i < len; i++) { |
| let num1 = parseInt(v1[i]), |
| num2 = parseInt(v2[i]); |
| |
| if (num1 > num2) { |
| return 1; |
| } else if (num1 < num2) { |
| return -1; |
| } |
| } |
| |
| return 0; |
| } |
| function compareVersion() { |
| if (versionInfo.v1 == "") { |
| uni.showToast({ |
| title: "请输入版本1!", |
| icon: "error", |
| }); |
| return; |
| } |
| if (versionInfo.v2 == "") { |
| uni.showToast({ |
| title: "请输入版本2!", |
| icon: "error", |
| }); |
| return; |
| } |
| let res = proxy.$apis.utils.compareVersion(versionInfo.v1, versionInfo.v2); |
| switch (res) { |
| case 0: |
| versionInfo.text = "版本1和版本2相同!"; |
| break; |
| case 1: |
| versionInfo.text = "版本1比版本2要新!"; |
| break; |
| case -1: |
| versionInfo.text = "版本1比版本2要老!"; |
| break; |
| default: |
| break; |
| } |
| } |
| async function getVersion() { |
| let system = uni.getSystemInfoSync(); |
| let opts = { |
| url: proxy.$apis.urls.version, |
| method: "get", |
| }; |
| let data = await proxy.$http.request(opts), |
| v1 = system.appVersion, |
| v2 = data.install.version; |
| versionInfo.v1 = v1; |
| versionInfo.v2 = v2; |
| checkInfo.current = v1; |
| checkInfo.online = v2; |
| checkInfo.data = data; |
| getSource(); |
| console.log("请求结果:", data); |
| } |
| function checkUpdate() { |
| let result = proxy.$apis.utils.compareVersion(checkInfo.current, checkInfo.online); |
| checkInfo.result = result; |
| |
| if (checkInfo.result == 1) { |
| uni.showToast({ |
| title: "已是最新版本!", |
| icon: "success", |
| }); |
| return; |
| } |
| |
| if (checkInfo.result == -1) { |
| let { des, url } = checkInfo.data.install; |
| checkInfo.type = "install"; |
| installSet(des, url); |
| } |
| |
| if (checkInfo.result == 0) { |
| checkSource(); |
| } |
| } |
| |
| async function getSource() { |
| let { source } = checkInfo.data, |
| v1 = 0, |
| v2 = 0, |
| local = await proxy.$apis.utils.storeage({ |
| type: "get", |
| isSync: true, |
| key: "source", |
| }); |
| if (local.code == 1) { |
| v1 = local.data; |
| } else { |
| proxy.$apis.utils.storeage({ |
| type: "set", |
| isSync: true, |
| key: "source", |
| val: 0, |
| }); |
| v1 = 0; |
| } |
| let { version } = source; |
| v2 = version; |
| checkInfo.currentSource = v1; |
| checkInfo.onlineSource = v2; |
| } |
| function checkSource() { |
| if (checkInfo.currentSource >= checkInfo.onlineSource) { |
| uni.showToast({ |
| title: "已是最新版本!", |
| icon: "success", |
| }); |
| return; |
| } |
| let { des, url } = checkInfo.data.source; |
| checkInfo.type = "source"; |
| installSet(des, url); |
| } |
| function installSet(content, url) { |
| uni.showModal({ |
| title: "系统消息", |
| content, |
| cancelText: "取消更新", |
| cancelColor: "#333", |
| confirmText: "立马更新", |
| confirmColor: "#24afd6", |
| success(res) { |
| if (res.confirm) { |
| downloadFile(url); |
| } |
| }, |
| fail() { |
| uni.showToast({ |
| title: "更新失败!", |
| icon: "error", |
| }); |
| }, |
| }); |
| } |
| async function downloadFile(url) { |
| checkInfo.showProgress = true; |
| downloadTime(); |
| let opts = { |
| url, |
| }; |
| let data = await proxy.$http.download(opts); |
| if (data.code === 103) { |
| checkInfo.showProgress = false; |
| checkInfo.currentProgress = 0; |
| uni.showToast({ |
| title: "下载失败!", |
| icon: "error", |
| }); |
| return; |
| } |
| if (data) { |
| checkInfo.currentProgress = 100; |
| installFile(data); |
| } |
| } |
| function downloadTime() { |
| checkInfo.downloader = setInterval(() => { |
| if (checkInfo.currentProgress < 90) { |
| let randomNum = Math.ceil(Math.random() * 5); |
| checkInfo.currentProgress += randomNum; |
| } else { |
| clearInterval(checkInfo.downloader); |
| } |
| }, 1000); |
| } |
| function installFile(file) { |
| if (plus) { |
| uni.showLoading({ |
| title: "文件安装中...", |
| }); |
| plus.runtime.install( |
| file, |
| { |
| force: true, |
| }, |
| (res) => { |
| uni.hideLoading(); |
| checkInfo.showProgress = false; |
| checkInfo.currentProgress = 0; |
| proxy.$apis.utils.storeage({ |
| type: "set", |
| isSync: true, |
| key: "source", |
| val: checkInfo.data.source.version, |
| }); |
| plus.runtime.restart(); |
| }, |
| (err) => { |
| uni.hideLoading(); |
| checkInfo.showProgress = false; |
| checkInfo.currentProgress = 0; |
| uni.showToast({ |
| title: "安装失败!", |
| icon: "error", |
| }); |
| } |
| ); |
| } else { |
| uni.showToast({ |
| title: "此版本不支持!", |
| icon: "error", |
| }); |
| } |
| } |
微信小程序更新
根据微信小程序官网的文档,更新方法如下:
微信小程序检测更新文档
| const updateManager = wx.getUpdateManager(); |
| |
| updateManager.onCheckForUpdate(function (res) { |
| |
| console.log(res.hasUpdate); |
| }); |
| |
| updateManager.onUpdateReady(function () { |
| wx.showModal({ |
| title: "更新提示", |
| content: "新版本已经准备好,是否重启应用?", |
| success: function (res) { |
| if (res.confirm) { |
| |
| updateManager.applyUpdate(); |
| } |
| }, |
| }); |
| }); |
| |
| updateManager.onUpdateFailed(function () { |
| |
| }); |
案例展示
h5 端效果
- 比较版本方法示例

APP 端效果
最后
以上就是版本更新和热更新实现方法的主要内容,有不足之处,请多多指正。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)