因为uni-app提供的 uni-upgrade-center 需要配合uniCloud使用,所以,需要寻找在不使用 uniCloud 的情况下实现 App 的版本检查和自动更新功能方法。在 uni-app 中实现 App 更新功能,主要依赖于 HTML5+ 规范提供的 API 和 uni-app 的跨平台能力。
1. 整体流程
需要更新 已是最新 立即更新 成功 失败 稍后更新 启动检查更新 请求服务器版本信息 版本比较 显示更新对话框 提示已是最新版本 用户选择 下载更新文件 显示下载进度 安装更新 安装结果 重启应用 提示安装失败 继续使用
2. 核心 API 详解
2.1 uni.getSystemInfoSync()
功能:获取获取系统信息
关键返回值::
javascript
{
appName: "宠医宝",
appVersion: "1.0.0",
appVersionCode: 100,
appWgtVersion: "1.0.0",
platform: '', // 客户端平台(ios/android)
system: '', // 操作系统版本
model: '', // 设备型号
screenWidth: 375, // 屏幕宽度
screenHeight: 667 // 屏幕高度
}
使用示例:
javascript
const systemInfo= uni.getSystemInfoSync();
console.log('运行平台:', systemInfo.platform); // "ios" 或 "android"
console.log('当前版本:', systemInfo.appVersion); // 如: "1.2.0"
console.log('版本码:', systemInfo.appVersionCode); // 如: "120"
2.2 uni.downloadFile()
功能:下载文件资源到本地
语法:
javascript
const downloadTask = uni.downloadFile({
url: '', // 下载资源的 URL(必需)
header: {}, // HTTP 请求 Header
timeout: 60000, // 超时时间,单位 ms
success: function (res) { }, // 下载成功的回调函数
fail: function (err) { }, // 下载失败的回调函数
complete: function () { } // 接口调用结束的回调函数
});
返回值 downloadTask 对象方法::
json
{
onProgressUpdate: Function, // 监听下载进度变化
abort: Function, // 中断下载任务
onHeadersReceived: Function, // 监听 HTTP Response Header
offProgressUpdate: Function, // 取消监听下载进度变化
offHeadersReceived: Function // 取消监听 HTTP Response Header
}
使用示例:
javascript
// 1. 基础下载
const downloadTask = uni.downloadFile({
url: 'https://example.com/app-release.apk',
success: (res) => {
if (res.statusCode === 200) {
console.log('下载成功,临时文件路径:', res.tempFilePath);
}
}
});
// 2. 监听下载进度
downloadTask.onProgressUpdate((res) => {
console.log('下载进度:', res.progress + '%');
console.log('已下载:', res.totalBytesWritten + ' bytes');
console.log('总大小:', res.totalBytesExpectedToWrite + ' bytes');
});
// 3. 中断下载
downloadTask.abort();
2.4 plus.runtime.install()
功能:安装下载的文件
语法:
javascript
plus.runtime.install(filePath, options, successCB, errorCB);
参数说明:
filePath{String}:安装文件路径(必需)options{Object}:安装选项force{Boolean}:是否强制安装(默认 false)
successCB{Function}:安装成功回调函数errorCB{Function}:安装失败回调函数
使用示例:
javascript
plus.runtime.install(res.tempFilePath, {
force: false
}, (installRes) => {
console.log('安装成功');
// 通常在此处重启应用
plus.runtime.restart();
}, (error) => {
console.error('安装失败:', error.message);
});
注意事项:
- 需要文件读写权限
- Android 需要特殊权限才能安装 APK
- iOS 由于系统限制无法直接安装,通常跳转到 App Store
2.5 plus.runtime.restart()
功能:重启当前应用
使用示例:
javascript
// 安装成功后重启应用
plus.runtime.install(filePath, {}, () => {
plus.runtime.restart(); // 重启应用使更新生效
}, (error) => {
console.error('安装失败:', error);
});
2.6 plus.runtime.quit()
功能:退出应用
使用场景:
javascript
// 强制更新时用户拒绝更新,退出应用
if (this.updateInfo.forceUpdate) {
plus.runtime.quit();
}
注意事项:
- 会完全退出应用进程
3. 权限配置
Android 平台需要配置相应权限:
json
{
"app-plus": {
"permissions": {
"android": {
"permissions": [
"<uses-permission android:name=\"android.permission.INTERNET\"/>",
"<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
"<uses-permission android:name=\"android.permission.REQUEST_INSTALL_PACKAGES\"/>"
]
}
}
}
}
4. 组件化设计
html
<template>
<view class="update-manager">
<!-- 检查更新按钮 -->
<button class="check-update-btn" @click="checkUpdate">
<text>检查更新</text>
</button>
<!-- 更新进度弹窗 -->
<uni-popup ref="progressPopup" type="center">
<view class="progress-popup">
<view class="progress-content">
<text class="progress-title">正在下载更新...</text>
<progress :percent="downloadProgress" show-info stroke-width="8" class="progress-bar" />
<button type="warn" @click="cancelDownload">取消下载</button>
</view>
</view>
</uni-popup>
</view>
</template>
5. 核心实现
5.1 版本检查流程
javascript
// 检查更新 - 完整流程
async checkUpdate() {
try {
// 步骤1: 请求服务器获取最新版本信息
const res = await new Promise((resolve, reject) => {
uni.request({
url: "http://192.168.6.222/check-version",
method: "GET",
success: (res) => resolve(res),
fail: (err) => reject(err),
});
});
if (res.data.code === 200) {
// 步骤2: 保存服务端版本信息
this.updateInfo = res.data.data;
// 步骤3: 获取系统信息
const systemInfo = uni.getSystemInfoSync();
// 步骤4: 版本比较
const updateResult = this.checkVersionUpdate(systemInfo);
if (updateResult.needsUpdate) {
// 需要更新,显示更新对话框
this.showUpdateDialog(updateResult.platform);
} else {
// 已是最新版本
uni.showToast({
title: "当前已是最新版本",
icon: "success",
});
}
}
} catch (error) {
console.error("检查更新失败:", error);
uni.showToast({
title: "检查更新失败",
icon: "none",
});
}
}
// 版本比较逻辑
checkVersionUpdate(systemInfo) {
// 使用版本码进行数值比较(推荐)
const needsUpdate = this.updateInfo.versionCode > systemInfo.appVersionCode;
// 获取平台信息
const platform = systemInfo.platform;
return {
needsUpdate,
platform,
};
}
要点:
- 使用 versionCode 而非 version 进行版本比较更准确:版本码是数字,便于比较,避免了版本号字符串比较的复杂性(如 1.10 < 1.2 的问题)
- Promise 封装 uni.request 使代码更清晰
5.2 下载与安装流程
javascript
// 下载并更新 (Android专用) - 详细解析
async downloadAndUpdate() {
// 步骤1: 显示下载进度弹窗
this.showProgress();
this.downloadProgress = 0;
// 步骤2: 开始下载文件
this.downloadTask = uni.downloadFile({
url: this.updateInfo.url, // 从服务端获取的下载地址
success: (res) => {
if (res.statusCode === 200) {
// 步骤3: 下载成功,开始安装
plus.runtime.install(
res.tempFilePath, // 下载得到的临时文件路径
{ force: false }, // 安装选项
(installRes) => {
// 安装成功回调
this.hideProgress();
uni.showModal({
title: "更新下载完成",
content: "是否立即重启应用?",
success: (modalRes) => {
if (modalRes.confirm) {
plus.runtime.restart(); // 重启应用使更新生效
}
},
});
},
(error) => {
// 安装失败回调
this.hideProgress();
console.error("安装失败:", error);
this.handleInstallError(error);
}
);
} else {
this.handleDownloadError();
}
},
fail: (err) => {
// 下载失败处理
this.handleDownloadError();
},
});
// 步骤4: 监听下载进度并更新 UI
this.downloadTask.onProgressUpdate((res) => {
this.downloadProgress = res.progress;
});
}
5.3 平台差异化处理
javascript
// 显示更新对话框 - 平台适配
showUpdateDialog(platform) {
const content = `发现新版本 ${this.updateInfo.title},此版本为重要更新,请及时升级!\n\n更新内容:\n${this.updateInfo.updateInfo || "功能优化与bug修复"}`;
uni.showModal({
title: "发现新版本",
content: content,
showCancel: true,
confirmText: "立即更新",
cancelText: "稍后更新",
success: (res) => {
if (res.confirm) {
// 根据平台执行不同更新操作
if (platform === "ios") {
this.goToAppStore(); // iOS跳转App Store
} else if (platform === "android") {
this.downloadAndUpdate(); // Android下载安装
}
} else if (res.cancel && this.updateInfo.forceUpdate) {
// 强制更新时用户取消则退出应用
plus.runtime.quit();
}
},
});
}
// 跳转到App Store
goToAppStore() {
if (this.updateInfo.appStoreUrl) {
plus.runtime.openURL(this.updateInfo.appStoreUrl);
} else {
const appStoreUrl = "https://apps.apple.com/app/id您的应用ID";
plus.runtime.openURL(appStoreUrl);
}
}
5.4 取消下载
javascript
// 取消下载
cancelDownload() {
if (this.downloadTask) {
this.downloadTask.abort();
this.hideProgress();
uni.showToast({
title: '已取消下载',
icon: 'none'
});
}
}
5.5 错误处理
javascript
// 处理下载错误
handleDownloadError() {
this.hideProgress();
uni.showModal({
title: "下载失败",
content: "更新文件下载失败,请检查网络连接后重试",
showCancel: true,
success: (res) => {
if (this.updateInfo.forceUpdate) {
plus.runtime.quit();
}
},
});
},