App启动时需在onLaunch和节流后的onShow中主动检测版本,比对本地storage存储的versionCode与服务端返回的纯数字version_code,强制更新时直跳下载,Android注意存储权限与安装路径,iOS需企业签名plist跳转。

App启动时怎么触发版本检测
uni-app在App端不能靠网页刷新机制,得在onLaunch里主动拉取服务端版本信息。iOS和Android都支持,但要注意:冷启动才可靠,热更新或后台切前台时onLaunch不执行,得配合onShow做兜底。
常见错误是只在onLaunch里请求一次,结果用户从后台唤起App时完全没检查——这时候用户可能还在用旧版,但你根本没机会提示。
- 必须同时监听
onLaunch和onShow,且onShow要加节流(比如5分钟内只查一次) - 服务端接口建议返回
version_code(数字)、version_name(字符串)、force_update(布尔)、download_url(APK/IPA直链) - 客户端用
uni.getSystemInfoSync().platform区分iOS/Android,决定走哪个下载地址
怎么比对本地和远程版本号
别直接用uni.getSystemInfoSync().version——它返回的是App的Bundle Version(iOS)或versionName(Android),但这个值在uni-app里实际是manifest.json里填的name字段,不是你打包时写的versionCode。真正该比的是versionCode,它才是可排序、可比较的整数。
所以你得自己存一个本地版本码:首次安装或升级后,把versionCode写进uni.setStorageSync('app_version_code', 102);后续每次启动都读这个值去和服务端的version_code对比。
- 服务端返回的
version_code必须是纯数字,比如102,不能是1.2.3 - 本地
versionCode要和HBuilderX打包配置里的versionCode严格一致(manifest.json →"versionCode") - 如果服务端返回
force_update: true,就跳过“是否更新”弹窗,直接调起下载
下载APK失败的几个硬坑
Android端调uni.downloadFile下载APK后,用uni.installApk安装,但90%的失败都卡在这几步:
- Android 11+要求声明
android:requestLegacyExternalStorage="true",否则uni.downloadFile写入外部存储失败(报错fail permission denied) - 下载路径必须用
uni.env.USER_DATA_PATH或uni.env.TEMP_FILE_PATH,不能拼/sdcard/xxx.apk——后者在Android 10+会静默失败 - 安装前要校验文件MD5,服务端必须提供
file_md5字段,否则用户可能装上半截损坏包 - iOS没法自动安装IPA,
uni.installApk在iOS下无效果,只能跳转itms-services://?action=download-manifest&url=xxx.plist,而这个plist必须由企业证书签名且托管在HTTPS域名下
灰度更新怎么控制下发范围
服务端接口不能只返回“有新版本”,得带条件判断逻辑。最简单有效的方式是在请求头或参数里传channel(渠道号)、device_id(设备唯一标识)、user_id(登录态ID),然后服务端按规则放行。
比如你想让10%的Android用户先升级,服务端可以:if (platform === 'android' && Math.random() ;或者更稳妥地用<code>device_id % 100 做一致性灰度。
- 客户端不要自己算灰度比例,所有策略必须由服务端控制,否则发错包没法回滚
-
device_id推荐用uni.getSystemInfoSync().deviceId,它在App内稳定,重装不重置 - 灰度期间,服务端返回的
force_update应始终为false,避免非灰度用户被误强更
版本检测这事,最难的不是写代码,而是服务端响应结构得和客户端存的versionCode对齐,还有Android权限和iOS分发链路那几处隐性约束——漏一个,整个更新流程就断在用户手机上,还查不出原因。


















