鸿蒙掌上驾考宝典应用开发37:检测应用更新组件——check_app_update
·
第37篇:检测应用更新组件——check_app_update

一、引言
应用更新是保持应用活力的重要功能,它让开发者能够及时修复 Bug、添加新功能、优化用户体验。DriverLicenseExam 项目的 check_app_update 组件封装了完整的应用更新检测流程,包括版本对比、新版本信息展示、下载更新等。本文将深入解析其实现。
二、组件架构
2.1 组件目录结构
check_app_update/
├── src/main/ets/
│ ├── components/
│ │ └── FindNewVersion.ets ← 发现新版本页面
│ ├── model/
│ │ └── Params.ets ← 参数模型
│ └── utils/
│ ├── AppUpdateUtil.ets ← 更新工具类
│ └── DialogController.ets ← 弹窗控制
├── Index.ets ← 模块导出
└── oh-package.json5 ← 模块配置
2.2 更新流程
应用启动 / 手动检查
│
▼
AppUpdateUtil.checkUpdate()
│
├── 请求服务器获取最新版本信息
│
▼
版本对比(versionCode)
│
├── 无新版本 → 不提示
│
└── 有新版本 → 展示更新弹窗
│
├── 普通更新
│ ├── "稍后更新" → 关闭弹窗
│ └── "立即更新" → 下载安装
│
└── 强制更新
├── 不可关闭弹窗
└── 必须更新后才能使用
三、版本信息模型
3.1 数据结构
// Params.ets
export interface UpdateParams {
versionName: string; // 新版本名(如 "1.1.0")
versionCode: number; // 新版本号(如 1001000)
updateDesc: string; // 更新说明
downloadUrl: string; // 下载地址
forceUpdate: boolean; // 是否强制更新
packageSize: string; // 安装包大小(如 "12.5MB")
publishDate: string; // 发布日期
}
3.2 版本号对比逻辑
鸿蒙应用的版本号使用 versionCode 进行对比,versionCode 是一个整数,每次发布递增:
// AppScope/app.json5
{
"versionCode": 1000000,
"versionName": "1.0.6"
}
推荐的 versionCode 编码规则:
1.0.0 → 1000000
1.0.1 → 1000001
1.0.9 → 1000009
1.1.0 → 1001000
1.2.3 → 1002003
2.0.0 → 2000000
四、更新工具类
4.1 AppUpdateUtil 实现
// AppUpdateUtil.ets
export class AppUpdateUtil {
private static downloadTask: request.agent.Task | null = null;
// 检查更新
static async checkUpdate(): Promise<UpdateParams | null> {
try {
// 请求服务器获取最新版本信息
const response = await https.getUpdateInfo();
const currentVersion = 1000000; // 当前版本号
if (response.versionCode > currentVersion) {
Logger.info('AppUpdateUtil', 'New version found: ' + response.versionName);
return response;
}
Logger.info('AppUpdateUtil', 'Already up to date');
return null;
} catch (error) {
Logger.error('AppUpdateUtil', 'check update failed: ' + error.message);
return null;
}
}
// 下载更新包
static async downloadUpdate(downloadUrl: string): Promise<boolean> {
try {
// 创建下载任务
const context = getContext();
const downloadPath = context.filesDir + '/update.hap';
// 使用下载代理
const config: request.agent.Config = {
url: downloadUrl,
filePath: downloadPath,
background: true,
network: request.agent.Network.WIFI,
};
this.downloadTask = await request.agent.create(config);
await this.downloadTask.start();
Logger.info('AppUpdateUtil', 'Download completed: ' + downloadPath);
return true;
} catch (error) {
Logger.error('AppUpdateUtil', 'download failed: ' + error.message);
return false;
}
}
// 安装更新包
static async installUpdate(filePath: string): Promise<void> {
try {
// 调用系统安装器
const bundleInstaller = getContext().getApplicationContext()
.getBundleInstaller();
await bundleInstaller.install(filePath);
} catch (error) {
Logger.error('AppUpdateUtil', 'install failed: ' + error.message);
}
}
// 获取下载进度
static getDownloadProgress(): number {
if (this.downloadTask) {
return this.downloadTask.progress;
}
return 0;
}
}
五、更新弹窗组件
5.1 FindNewVersion 组件
// FindNewVersion.ets
@ComponentV2
export struct FindNewVersion {
@Local updateInfo: UpdateParams | null = null;
@Local downloadProgress: number = 0;
@Local isDownloading: boolean = false;
aboutToAppear() {
AppUpdateUtil.checkUpdate().then((info) => {
this.updateInfo = info;
});
}
build() {
if (this.updateInfo) {
Column() {
// 更新图标
Image($r('app.media.ic_update'))
.width(64).height(64)
.margin({ top: 16 });
// 标题
Text('发现新版本')
.fontSize(20)
.fontWeight(FontWeight.Bold)
.margin({ top: 12 });
// 版本号
Text('v' + this.updateInfo.versionName)
.fontSize(14)
.fontColor('#999')
.margin({ top: 4 });
// 更新说明
Scroll() {
Text(this.updateInfo.updateDesc)
.fontSize(14)
.lineHeight(22)
.padding(16);
}
.height(120);
// 下载进度条
if (this.isDownloading) {
Progress({ value: this.downloadProgress, total: 100 })
.width('100%')
.color('#64BB5C')
.margin({ top: 12 });
Text('下载中 ' + this.downloadProgress + '%')
.fontSize(12)
.fontColor('#999');
}
// 按钮
Row({ space: 16 }) {
if (!this.updateInfo.forceUpdate) {
// 非强制更新:显示"稍后更新"按钮
Button('稍后更新')
.fontColor('#666')
.backgroundColor('#F5F5F5')
.borderRadius(20)
.onClick(() => {
this.closeDialog();
});
}
Button(this.isDownloading ? '下载中...' : '立即更新')
.fontColor('#fff')
.backgroundColor('#64BB5C')
.borderRadius(20)
.enabled(!this.isDownloading)
.onClick(() => {
this.startUpdate();
});
}
.margin({ top: 16, bottom: 16 });
}
.padding(24)
.width('85%')
.borderRadius(16)
.backgroundColor($r('sys.color.comp_background_primary'));
}
}
startUpdate() {
this.isDownloading = true;
AppUpdateUtil.downloadUpdate(this.updateInfo.downloadUrl).then((success) => {
if (success) {
showToast('下载完成,正在安装...', this.getUIContext());
// 安装更新
} else {
showToast('下载失败,请检查网络', this.getUIContext());
}
this.isDownloading = false;
});
}
}
5.2 强制更新 vs 普通更新
| 特性 | 普通更新 | 强制更新 |
|---|---|---|
| 弹窗可关闭 | 是 | 否 |
| 显示"稍后更新" | 是 | 否 |
| 使用场景 | 功能优化 | 安全修复、重大 Bug |
| 用户体验 | 用户可选择 | 必须更新 |
六、更新策略
6.1 更新检查时机
// 方案1:应用启动时自动检查
aboutToAppear() {
AppUpdateUtil.checkUpdate();
}
// 方案2:用户手动检查
Button('检查更新')
.onClick(() => {
AppUpdateUtil.checkUpdate().then((info) => {
if (info) {
showToast('发现新版本:v' + info.versionName, this.getUIContext());
} else {
showToast('已是最新版本', this.getUIContext());
}
});
});
// 方案3:定时检查(后台)
setInterval(() => {
AppUpdateUtil.checkUpdate();
}, 24 * 60 * 60 * 1000); // 每天检查一次
6.2 更新说明格式
更新说明建议使用结构化的格式:
功能新增:
- 新增深色模式支持
- 新增服务卡片
功能优化:
- 优化答题页面加载速度
- 优化字体显示效果
Bug 修复:
- 修复搜索功能某些关键词查找失败的问题
- 修复偶现的闪退问题
七、总结
检测应用更新组件实现了完整的更新流程:
- 版本检测:通过 versionCode 对比判断是否有新版本
- 信息展示:展示新版本号、更新说明、安装包大小
- 下载更新:使用下载代理下载安装包
- 安装更新:调用系统安装器安装
- 强制更新:支持强制更新场景
关键源码文件:
components/check_app_update/src/main/ets/components/FindNewVersion.ets— 更新弹窗组件components/check_app_update/src/main/ets/model/Params.ets— 版本信息模型components/check_app_update/src/main/ets/utils/AppUpdateUtil.ets— 更新工具类components/check_app_update/src/main/ets/utils/DialogController.ets— 弹窗控制
更多推荐




所有评论(0)