
第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(): PromiseUpdateParams | 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): Promiseboolean { 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): Promisevoid { 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— 弹窗控制