uni-app app端静默升级不能靠uni.downloadfile+uni.installdocument实现,因ios禁止静默安装,android 8.0+需用户授权且必显系统安装页;真正静默的只有wgt热更新,仅限5+app引擎,通过替换webview资源实现无感生效。

uni-app App端静默升级为什么不能靠 uni.downloadFile + uni.installDoucment 直接搞定
因为 iOS 完全禁止静默安装,而 Android 从 8.0(API 26)起强制要求用户授权 REQUEST_INSTALL_PACKAGES 权限,且安装界面必须显式弹出——所谓“静默”仅指不跳转到应用市场、不依赖用户手动点击下载按钮,但最终安装动作无法绕过系统确认页。
真正能走静默路径的,只有 wgt 包热更新(仅限 uni-app 自有运行环境,即 5+App 引擎)。它不涉及 APK 安装,而是替换 webview 资源,所以能无感生效。
- wgt 升级只对使用
uni-app编译为「原生渲染」或「自定义基座」的 App 有效;HBuilderX 打的标准云打包基座才支持 - 微信小程序、H5、快应用等其他平台不支持 wgt
- 升级后需调用
uni.reLaunch或plus.runtime.restart()才会加载新资源,否则仍运行旧代码
怎么用 plus.runtime.getProperty 和 plus.runtime.install 检查并安装 wgt
必须通过 5+ API 拿到本地版本号和远程 wgt 的 versionCode 对比,再触发下载安装。不能只靠 HTTP 状态码或文件名判断是否需要更新。
-
plus.runtime.getProperty返回的是当前 wgt 的versionCode(数字),不是version(字符串),对比时务必统一类型 -
plus.runtime.install的第二个参数是回调对象,success回调里必须调用plus.runtime.restart(),否则新包不会启用 - 下载 wgt 建议用
plus.downloader.createDownload而非uni.downloadFile,前者支持断点续传、进度监听,且返回的filename是绝对路径,可直接传给install
const dt = plus.downloader.createDownload('https://xxx.com/app.wgt', {
method: 'GET'
}, (d, status) => {
if (status === 200) {
plus.runtime.install(d.filename, {}, () => {
plus.runtime.restart(); // 关键!不写这句,升级白做
}, console.error);
}
});
dt.start();
Android 上 wgt 静默升级失败的三个典型错误现象
不是代码写错,而是环境或配置没到位:
- 报错
install wgt fail: invalid wgt file→ wgt 包未用 HBuilderX 正确打包(必须勾选「生成 wgt 包」,且目标平台选「App」,不能用「通用」或「H5」模式) - 升级后页面白屏或样式错乱 → 新 wgt 中引用了旧版
uni-app的 API(如uni.getSystemInfoSync在低版本 5+ 引擎中不存在),需检查基座版本兼容性 - 反复提示“正在升级”但无反应 → 服务器返回的 wgt 文件 MIME 类型不是
application/octet-stream,Nginx/Apache 需显式配置:add_type application/octet-stream .wgt;
如何让 wgt 升级真正“无感”:避免白屏、闪退、状态丢失
用户感知的“静默”,本质是视觉和交互不中断。这需要前端主动兜底,而不是等引擎自动 reload。
- 升级前用
uni.showLoading({ title: '更新中...' })遮盖界面,防止用户乱点;成功后uni.hideLoading(),再plus.runtime.restart() - 不要在
onLaunch或onShow里立刻请求升级,先用setTimeout延迟 1–2 秒,避开首屏渲染卡顿 - 如果业务依赖 Vuex/Pinia 状态,升级前把关键数据存到
uni.setStorageSync,重启后在onLaunch里恢复——plus.runtime.restart()会清空内存,但本地存储保留
最麻烦的其实是 wgt 版本管理和灰度发布:每次发新版都得改 manifest.json 的 versionCode,还得配套一套服务端下发策略。这点没人替你扛,得自己搭个轻量接口。










