应先用 uni.getSystemInfoSync().platform 同步判断平台:仅当值为 "ios" 或 "android" 时执行原生更新逻辑,避免在 H5、小程序或 devtools 环境调用 plus.runtime.install 报错;版本比较需拆分数字逐段比对,弹窗需加全局标志防重复触发。

如何判断当前运行环境是 App 而非 H5 或小程序
直接调用 uni.getUpdateManager 会报错,因为它是微信小程序专属 API,App 端完全不识别。真机运行时必须靠 uni.getSystemInfoSync().platform 判断——返回值是 "ios" 或 "android" 才能走原生更新逻辑;H5 和小程序环境下这个字段可能为空、为 "web" 或根本不可用,此时应跳过检查。
常见错误现象:TypeError: Cannot read property 'install' of undefined,本质是误在非 App 环境调用了 plus.runtime.install。
- 务必在调用任何更新逻辑前加判断:
if (platform === 'ios' || platform === 'android') - 不要依赖
uni.getSystemInfo异步版本,onShow中需同步获取,否则弹窗时机错乱 - 模拟器里
platform可能返回"devtools",也得纳入排除条件
怎么比对版本号才不会被 1.10.0
manifest.json 里的 version 字段实际对应的是“版本名称”(即 name),不是数字型的 versionCode;后端接口返回的最新版号也必须统一为字符串格式,否则用 parseFloat 或直接 > 比较会导致排序错乱。
推荐做法是用语义化版本比较函数,比如简单拆分再逐段比对:
function compareVersion(v1, v2) {
const a = v1.split('.').map(Number);
const b = v2.split('.').map(Number);
for (let i = 0; i < Math.max(a.length, b.length); i++) {
const n1 = a[i] || 0;
const n2 = b[i] || 0;
if (n1 > n2) return 1;
if (n1 < n2) return -1;
}
return 0;
}
- 后端返回的 version 字段必须和 manifest.json 的
name字段格式一致(如都写成"1.2.3-beta") - 避免在 manifest.json 里混用
1.2和1.2.0,同一项目保持小数点位数统一 - 测试时手动改 manifest.json 的
name后,必须重新打包——热更新不会刷新该值
Android 安装 APK 和 iOS 跳转 TestFlight 的关键差异
Android 调用 plus.runtime.install 需要 REQUEST_INSTALL_PACKAGES 权限,且从 Android 8.0 开始必须显式声明并请求;iOS 则完全无法静默安装,只能跳转到 TestFlight 链接或企业签名页,plus.runtime.openURL 是唯一可行路径。
- Android:下载完 APK 后必须传绝对路径(如
/storage/emulated/0/Download/app-release.apk),相对路径会失败 - iOS:链接必须是苹果官方 TestFlight 地址(
https://testflight.apple.com/join/xxx)或企业签名页,跳转前建议用uni.getNetworkType检查网络,避免无网时白屏 - 两者都需处理失败回调:
plus.runtime.install的error回调里常出现"INSTALL_FAILED_UPDATE_INCOMPATIBLE",说明签名不一致,需提醒用户手动卸载旧版
为什么 onShow 里弹窗还会闪退或拦截
首页 onShow 是最常用触发点,但若此时页面栈未就绪、或用户正处在输入框聚焦、视频播放、地图拖拽等敏感状态,uni.showModal 或自定义弹窗组件会因平台限制被静默丢弃,甚至引发白屏。
真正安全的时机是:页面已渲染完成 + 用户无活跃交互 + 不在路由跳转中途。可用以下方式加固:
- 加一层防抖:
setTimeout(() => { showUpdateModal() }, 300),避开 Vue 渲染队列高峰 - 监听
blur事件确认输入框已失焦,或用document.activeElement排查焦点元素 - 避免在
onShow中连续调用多次弹窗逻辑,升级弹窗应设全局标志位isUpdateChecked = true防止重复触发 - 如果用了自定义弹窗组件(如
u-popup),确保其v-model绑定的变量在onShow后才设为true,而非提前响应
复杂点在于:iOS 上 TestFlight 跳转后无法回调,Android 安装后也无法自动重启,这些断点必须靠用户操作补全,不能假设流程全自动。


















