应用更新使用指导
自己分发的 App(发给同学、学校或企业内部用、比赛作品)没有应用市场帮忙推送更新。 应用更新组件让 App 自己检查服务器上的版本文件,发现新版后下载安装包并调起系统安装, 用户点几下就升级到新版本。
工作原理
App 启动 → 读服务器上的版本文件 → 版本号比自己大?
否 → 已是最新
是 → 弹出「发现新版本」→ 用户点更新 → 下载安装包(通知栏显示进度)
→ 检查安装包(同一个 App、版本更高)→ 调起系统安装 → 用户点「安装」→ 新版启动
必须同时满足三个条件,系统才允许覆盖安装:
| 条件 | 说明 |
|---|---|
| 包名相同 | 新版和旧版是同一个项目编译出来的 |
| 签名相同 | 用同一个账号编译。换账号编译的安装包签名不同,系统会拒绝覆盖 |
| 版本号更高 | 新版的屏幕属性「版本号」必须比旧版大 |
组件在安装前会自动检查包名和版本号,不满足时不安装,并触发更新失败(阶段,消息)(UpdateFailed)说明原因。
准备:版本文件
在任何能直接下载的地址放一个 JSON 文本文件(自己的网站、对象存储、网盘直链都可以),内容如下:
{
"versionCode": 2,
"versionName": "1.1",
"url": "https://example.com/myapp-1.1.apk",
"notes": "1. 新增夜间模式\n2. 修复登录问题",
"force": false
}
| 字段 | 必填 | 含义 |
|---|---|---|
| versionCode | 是 | 新版的版本号(整数),对应屏幕属性「版本号」 |
| url | 是 | 新版安装包的下载地址,浏览器打开能直接下载才行(不能是需要登录的网页) |
| versionName | 否 | 显示给用户看的版本名,如 1.1 |
| notes | 否 | 更新说明,\n 表示换行 |
| force | 否 | true 表示强制更新:对话框没有「稍后」 |
每次发布新版的步骤:
- 屏幕 Screen1 的属性里把版本号加 1(如 1 → 2),版本名按需修改(如 1.0 → 1.1);
- 编译出安装包(APK),上传到服务器;
- 修改版本文件:
versionCode改成新的版本号,url改成新安装包的地址。
已经装了旧版的用户下次打开 App 就会收到更新提示。
快速上手
拖一个应用更新组件到屏幕,搭一块代码:
when Screen1.Initialize() {
应用更新1.CheckUpdate("https://example.com/version.json")
}
完成。内置对话框会负责提示、下载进度和安装。
案例一:设置页里的「检查更新」按钮
启动时自动检查之外,设置页再放一个按钮,并显示当前版本:
when Screen1.Initialize() {
标签_版本.Text = join("当前版本 ", 应用更新1.CurrentVersionName)
}
when 按钮_检查更新.Click() {
标签_状态.Text = "正在检查…"
应用更新1.CheckUpdate("https://example.com/version.json")
}
when 应用更新1.NoUpdate() {
标签_状态.Text = "已是最新版本"
}
when 应用更新1.UpdateFailed(阶段, 消息) {
标签_状态.Text = join(阶段, "失败:", 消息)
}
有新版时内置对话框照常弹出;没有新版或网络不通时,标签给出提示。
案例二:自己设计更新界面
把组件的使用内置对话框(UseBuiltInDialog)设为假,改用事件:
发现新版时显示一个更新区域,点按钮下载,下载时显示进度。
设计器里:一个垂直布局 垂直布局_更新(取消勾选「可见」),里面放标签 标签_说明、按钮 按钮_立即更新 和标签 标签_进度。
global 新版地址 = ""
when Screen1.Initialize() {
应用更新1.CheckUpdate("https://example.com/version.json")
}
when 应用更新1.UpdateAvailable(版本号, 版本名, 更新说明, 安装包地址, 强制更新) {
新版地址 = 安装包地址
标签_说明.Text = join("发现新版本 ", 版本名, ":", 更新说明)
垂直布局_更新.Visible = true
}
when 按钮_立即更新.Click() {
按钮_立即更新.Enabled = false
应用更新1.DownloadAndInstall(新版地址)
}
when 应用更新1.DownloadProgress(百分比) {
标签_进度.Text = join("正在下载 ", 百分比, "%")
}
when 应用更新1.DownloadCompleted(安装包路径) {
标签_进度.Text = "下载完成,请点「安装」"
}
when 应用更新1.UpdateFailed(阶段, 消息) {
标签_进度.Text = join(阶段, "失败:", 消息)
按钮_立即更新.Enabled = true
}
案例三:强制更新
旧版本有严重问题、必须升级时,把版本文件里的 force 设为 true:
- 使用内置对话框时,更新提示没有「稍后」按钮、不能关闭;下载完成后留一个不能关闭的「安装」对话框, 用户取消了系统安装回到 App 后还能再点安装;
- 自己设计界面时,在发现新版(版本号,版本名,更新说明,安装包地址,强制更新)(
UpdateAvailable)事件里判断「强制更新」参数, 为真时隐藏其它内容、只留更新按钮。
when 应用更新1.UpdateAvailable(版本号, 版本名, 更新说明, 安装包地址, 强制更新) {
if 强制更新 {
垂直布局_主界面.Visible = false
}
}
案例四:上架应用市场的 App
上架了应用市场的 App 一般要求通过市场更新,不能自己下载安装包。检查到新版后调用 应用工具的打开应用市场(包名留空为本应用),跳到本 App 的详情页让用户更新:
when 应用更新1.UpdateAvailable(版本号, 版本名, 更新说明, 安装包地址, 强制更新) {
应用工具1.OpenAppMarket("")
}
此时组件的使用内置对话框(UseBuiltInDialog)设为假;版本文件里的 url 随便填一个地址即可(必填)。
常见问题
| 现象 | 原因与处理 |
|---|---|
| 一直提示「已是最新」 | 版本文件的 versionCode 要大于手机上已装版本的「版本号」;在 AI 伴侣里测试时比较的是伴侣自己的版本号 |
| 更新失败:版本文件缺少整数 versionCode | 版本文件不是合法 JSON(多了逗号、用了中文引号),或 versionCode 写成了带小数点的版本名 |
| 更新失败:网络不通 / 服务器返回 404 | 版本文件地址在手机浏览器里能不能打开 |
| 下载完成后没有安装界面 | 安卓 8 及以上第一次更新要允许本 App「安装未知应用」;允许后回到 App 会自动继续 |
| 更新失败:不是本应用的安装包 | 安装包地址放错了 App;在 AI 伴侣里测试也会这样(伴侣的包名不同),请用编译出的 APK 测 |
| 更新失败:安装包版本号不高于当前版本号 | 编译新版前忘了把屏幕属性「版本号」加 1 |
| 系统提示「与已安装应用签名不一致」 | 新版不是用同一个账号编译的,只能卸载旧版后安装 |
| 下载很慢或失败 | 安装包地址要能直接下载;有些网盘分享页不是直链 |
平台说明
- 安卓:完整支持检查、下载、安装。上架 Google Play 的 App 不允许自行下载安装包更新,国内应用商店对此也有审核限制, 这类 App 请用案例四的方式;
- 鸿蒙:系统不允许 App 自行安装,「下载并安装」会触发更新失败;内置对话框的按钮改为「前往应用市场更新」, 需要 App 已上架华为应用市场;检查更新和各事件与安卓一致;
- AI 伴侣:可以试检查更新和下载,安装那一步请用编译出的 APK 测试。
扫码添加客服咨询