HarmonyOS应用开发实战:小事记 - 备份扩展 Ability 的注册机制与 onBackup/onRestore 生命周期
前言在移动应用中数据备份与恢复是保障用户数据安全的核心能力。HarmonyOS 提供了BackupExtensionAbility这一标准化的数据备份框架开发者只需要继承该类并实现onBackup和onRestore两个回调方法系统即可自动调度备份任务无需手动处理文件拷贝、压缩和传输等底层操作。本文以 小事记xiaoshiji_ohos_app 项目中的EntryBackupAbility.ets为切入点深入解析BackupExtensionAbility的注册机制、生命周期回调、备份配置文件和版本管理策略。核心特点简单易用API 设计直观上手成本低性能优异底层优化充分运行效率高扩展性强支持自定义配置和扩展本文参考 HarmonyOS 官方文档application-models.md 和 application-package-structure-stage.md。一、ExtensionAbility 体系概览1.1 ExtensionAbility 的设计理念ExtensionAbility是 HarmonyOS Stage 模型中用于后台任务的基类体系。与UIAbility不同ExtensionAbility 没有 UI 界面专注于在后台执行特定类型任务图ExtensionAbility 的各类扩展及其适用场景扩展类型系统类主要用途BackupExtensionAbilitykit.CoreFileKit数据备份与恢复ServiceExtensionAbilitykit.AbilityKit后台常驻服务FormExtensionAbilitykit.FormKit桌面卡片WidgetWorkSchedulerExtensionAbilitykit.BackgroundTasksKit延迟任务调度InputMethodExtensionAbilitykit.InputMethodKit输入法应用AccessibilityExtensionAbilitykit.AccessibilityKit无障碍服务1.2 备份扩展的独特性在众多 ExtensionAbility 类型中BackupExtensionAbility有几个独特之处系统自动调度— 备份任务由系统而非用户手动触发在设备充电、连接 Wi-Fi 且空闲时自动执行增量备份机制— 系统只备份发生变化的数据而非每次都全量备份配置驱动— 通过backup_config.json配置文件指定备份范围无需代码干预版本感知— 恢复时携带BundleVersion参数支持版本兼容性处理// EntryBackupAbility.ets — 小事记的备份扩展实现 import { hilog } from kit.PerformanceAnalysisKit; import { BackupExtensionAbility, BundleVersion } from kit.CoreFileKit; const DOMAIN 0x0000; export default class EntryBackupAbility extends BackupExtensionAbility { async onBackup() { hilog.info(DOMAIN, testTag, onBackup ok); await Promise.resolve(); } async onRestore(bundleVersion: BundleVersion) { hilog.info(DOMAIN, testTag, onRestore ok %{public}s, JSON.stringify(bundleVersion)); await Promise.resolve(); } }二、备份扩展的注册与配置2.1 在 module.json5 中注册备份扩展需要在module.json5的extensionAbilities数组中注册{ module: { extensionAbilities: [ { name: EntryBackupAbility, srcEntry: ./ets/entrybackupability/EntryBackupAbility.ets, type: backup, exported: false, metadata: [ { name: ohos.extension.backup, resource: $profile:backup_config } ] } ] } }各字段详解字段值说明nameEntryBackupAbility扩展名称模块内唯一srcEntry./ets/entrybackupability/EntryBackupAbility.ets实现文件的路径typebackup扩展类型必须为backupexportedfalse不对外暴露仅系统可调用metadata—包含系统约定的备份配置引用提示type字段的值必须与系统定义的类型严格一致backup不可拼写为backupdata或databackup。2.2 备份配置文件的定义metadata中的resource: $profile:backup_config引用了resources/base/profile/backup_config.json文件该文件定义了备份的具体范围// resources/base/profile/backup_config.json { allowToBackup: true, includes: [ data/storage/el2/database/, data/storage/el2/base/preferences/ ], excludes: [ data/storage/el2/base/cache/, data/storage/el2/base/temp/ ] }配置字段说明字段类型说明是否必须allowToBackupboolean是否允许备份✅includesstring[]需要备份的路径列表✅excludesstring[]排除的路径列表❌fullBackupOnlyboolean是否仅全量备份❌路径规则路径相对于data/storage/el2/base/应用的文件根目录支持目录路径以/结尾和文件路径不支持通配符*但目录路径会递归包含所有子文件2.3 文件分区模式备份路径中的el2指的是加密分区模式HarmonyOS 提供了两种文件分区分区模式常量说明存储内容EL1AreaMode.EL1设备级加密开机即可访问应用配置、缓存EL2AreaMode.EL2用户级加密需要解锁后访问用户数据库、偏好设置// 获取不同分区的路径 import { common } from kit.AbilityKit; let context this.context.getApplicationContext(); let el1Path context.getDatabaseDir(); // EL1 分区数据库路径 let el2Path context.getPreferencesDir(); // EL2 分区偏好设置路径小事记的备份配置包含了el2分区的数据库和偏好设置因为用户的事件数据LifeEvent和设置项都存储在这个分区中。三、onBackup 生命周期详解3.1 备份触发时机系统在以下场景会触发onBackup回调设备充电状态— 接入电源后网络条件— 连接 Wi-Fi非蜂窝网络空闲状态— 设备处于空闲状态时间间隔— 距离上次备份超过 24 小时以上条件全部满足时系统才会触发备份。开发者无法手动触发备份但可以通过onBackup回调中的代码执行自定义的预处理逻辑。3.2 onBackup 的完整实现当前小事记的onBackup只记录了日志但在生产环境中应该进行数据完整性校验// 增强版 onBackup 实现 import { hilog } from kit.PerformanceAnalysisKit; import { BackupExtensionAbility, BundleVersion } from kit.CoreFileKit; import { fileIo } from kit.CoreFileKit; const DOMAIN 0x0000; export default class EntryBackupAbility extends BackupExtensionAbility { async onBackup() { hilog.info(DOMAIN, testTag, onBackup started); try { // 1. 检查数据库完整性 await this.checkDatabaseIntegrity(); // 2. 清理过期缓存减少备份体积 await this.cleanExpiredCache(); // 3. 记录备份时间戳 await this.recordBackupTimestamp(); hilog.info(DOMAIN, testTag, onBackup completed); } catch (err) { hilog.error(DOMAIN, testTag, onBackup failed: %{public}s, JSON.stringify(err)); throw err; // 抛出异常系统会记录备份失败 } } private async checkDatabaseIntegrity(): Promisevoid { // 数据库完整性检查逻辑 // 如果数据损坏在此处抛出自定义异常 } private async cleanExpiredCache(): Promisevoid { let cacheDir this.context.cacheDir; // 清理 7 天前的缓存文件 // 减少备份体积 } private async recordBackupTimestamp(): Promisevoid { let lastBackupTime new Date().toISOString(); // 将备份时间写入偏好设置 // 用于在 UI 中展示上次备份时间 } }3.3 备份文件的解密与恢复系统在备份时会对数据进行加密。备份数据存储在云端用户无法直接查看备份文件内容只能通过onRestore恢复。四、onRestore 生命周期详解4.1 恢复触发场景onRestore在以下场景被触发用户在新设备登录— 首次启动应用时系统检测到云端有备份数据应用重装后— 卸载重装后系统自动恢复备份数据跨设备迁移— 通过华为账号将数据从旧设备迁移到新设备4.2 BundleVersion 版本管理onRestore的参数BundleVersion包含了备份数据的版本信息用于处理版本兼容性// BundleVersion 的数据结构 interface BundleVersion { major: number; // 主版本号 minor: number; // 次版本号 patch: number; // 补丁版本号 build: number; // 构建号 versionName: string; // 版本名称如 1.0.0 }4.3 版本兼容性处理在恢复数据时需要处理备份版本与当前应用版本不同的情况// 带版本兼容性处理的 onRestore 实现 async onRestore(bundleVersion: BundleVersion): Promisevoid { hilog.info(DOMAIN, testTag, onRestore called, version: %{public}s, JSON.stringify(bundleVersion)); try { // 1. 获取当前应用版本 let currentVersion this.getCurrentAppVersion(); // 2. 版本对比 if (this.isNewerVersion(bundleVersion, currentVersion)) { // 备份版本比当前应用版本新 → 数据降级处理 await this.downgradeData(bundleVersion, currentVersion); } else if (this.isOlderVersion(bundleVersion, currentVersion)) { // 备份版本比当前应用版本旧 → 数据迁移处理 await this.migrateData(bundleVersion, currentVersion); } else { // 版本相同 → 直接恢复 await Promise.resolve(); } // 3. 恢复完成后的回调 this.onRestoreCompleted(); hilog.info(DOMAIN, testTag, onRestore completed); } catch (err) { hilog.error(DOMAIN, testTag, onRestore failed: %{public}s, JSON.stringify(err)); throw err; } } private getCurrentAppVersion(): BundleVersion { // 从 Context 获取当前应用版本号 let appInfo this.context.applicationInfo; return { major: Math.floor(appInfo.versionCode / 1000000), minor: Math.floor((appInfo.versionCode % 1000000) / 10000), patch: Math.floor((appInfo.versionCode % 10000) / 100), build: appInfo.versionCode % 100, versionName: appInfo.versionName }; } private isNewerVersion(backup: BundleVersion, current: BundleVersion): boolean { if (backup.major current.major) return true; if (backup.major current.major backup.minor current.minor) return true; return false; } private isOlderVersion(backup: BundleVersion, current: BundleVersion): boolean { if (backup.major current.major) return true; if (backup.major current.major backup.minor current.minor) return true; return false; } private async downgradeData(backup: BundleVersion, current: BundleVersion): Promisevoid { // 备份版本更新 → 数据降级 // 例如备份中有新版本才有的字段需要降级处理 hilog.info(DOMAIN, testTag, Downgrading data from %{public}s to %{public}s, JSON.stringify(backup), JSON.stringify(current)); } private async migrateData(backup: BundleVersion, current: BundleVersion): Promisevoid { // 备份版本更旧 → 数据迁移 // 例如数据库 schema 变更需要执行 ALTER TABLE hilog.info(DOMAIN, testTag, Migrating data from %{public}s to %{public}s, JSON.stringify(backup), JSON.stringify(current)); } private onRestoreCompleted(): void { // 恢复完成后的回调例如弹出 Toast 提示用户 hilog.info(DOMAIN, testTag, Restore completed successfully); }4.4 版本号编码规范小事记的versionCode为1000000对应的版本编码规则如下// 版本号编码规则MAJOR * 1000000 MINOR * 10000 PATCH * 100 BUILD // 1.0.0.0 → 1000000 // 1.1.0.0 → 1010000 // 2.0.0.0 → 2000000版本名称versionCode分解1.0.0.01000000major1, minor0, patch0, build01.1.0.01010000major1, minor1, patch0, build01.2.3.41020304major1, minor2, patch3, build4五、备份与恢复的数据流5.1 完整备份流程[系统触发备份条件] ↓ 系统调用 BackupExtensionAbility.onBackup() ↓ onBackup 中执行预处理数据校验、清理缓存 ↓ 系统根据 backup_config.json 的 includes 路径收集文件 ↓ 跳过 excludes 路径中的文件 ↓ 系统对文件进行加密和压缩 ↓ 将加密数据上传到云端 ↓ onBackup 返回备份完成5.2 完整恢复流程[用户在新设备安装应用] ↓ 系统检测到云端有备份数据 ↓ 系统调用 BackupExtensionAbility.onRestore() ↓ onRestore 接收 BundleVersion 参数 ↓ 版本对比 → 执行数据迁移或降级 ↓ 系统解密备份数据 ↓ 将数据恢复到 includes 指定的路径 ↓ onRestore 返回恢复完成 ↓ 用户打开应用看到已恢复的数据5.3 备份范围测试测试场景预期结果测试方法新增一条事件记录下次备份包含该记录在应用中添加事件触发备份恢复后检查删除一条事件记录下次备份不再包含该记录删除事件触发备份恢复后检查变更应用设置备份包含新设置修改设置项触发备份恢复后检查备份文件完整性恢复后数据完整无误比较备份前后的数据记录总数六、备份扩展的异常处理6.1 常见异常场景异常场景原因处理方式onBackup超时数据量过大超过 30 秒分片处理或减少 includes 范围备份文件损坏存储介质故障在 onRestore 中增加完整性校验版本不兼容数据库 schema 变更在 onRestore 中实现数据迁移逻辑存储空间不足设备空间不足系统会自动跳过备份记录错误日志6.2 超时与重试策略// 大文件备份的超时处理 async onBackup(): Promisevoid { const BACKUP_TIMEOUT 25000; // 25 秒超时 const timeoutPromise new Promise((_, reject) { setTimeout(() reject(new Error(Backup timeout)), BACKUP_TIMEOUT); }); const backupPromise this.performBackup(); try { await Promise.race([backupPromise, timeoutPromise]); hilog.info(DOMAIN, testTag, Backup completed within timeout); } catch (err) { hilog.error(DOMAIN, testTag, Backup failed: %{public}s, JSON.stringify(err)); throw err; } } private async performBackup(): Promisevoid { // 实际的备份逻辑 await this.checkDatabaseIntegrity(); await this.cleanExpiredCache(); await this.recordBackupTimestamp(); }七、区别于 FA 模型的数据备份7.1 模型对比对比维度FA 模型Stage 模型备份方式手动处理文件 IOBackupExtensionAbility 框架配置方式无标准化配置backup_config.json声明式加密支持需自行实现系统自动加密增量备份不支持系统支持恢复回调无onRestore(BundleVersion)版本感知7.2 迁移建议从 FA 模型迁移到 Stage 模型时备份功能的迁移需要注意移除手动文件操作— 不再需要手动拷贝databases/目录下的文件添加备份配置— 创建backup_config.json文件声明备份范围实现回调方法— 在onBackup和onRestore中添加版本兼容性处理测试恢复流程— 确保数据在不同版本间可以正确恢复八、最佳实践总结8.1 备份配置的推荐策略{ allowToBackup: true, includes: [ data/storage/el2/database/, // 包含用户数据库 data/storage/el2/base/preferences/, // 包含偏好设置 data/storage/el2/base/haps/entry/files/ // 包含用户生成的文件 ], excludes: [ data/storage/el2/base/cache/, // 排除缓存 data/storage/el2/base/temp/, // 排除临时文件 data/storage/el1/base/preferences/ // 排除设备级配置 ] }8.2 onBackup 中的注意事项不要执行耗时操作— 系统对onBackup有超时限制30 秒不要修改用户数据—onBackup应该只读取数据不修改数据异常必须抛出— 如果备份失败应该抛出异常让系统感知避免网络请求— 备份时的网络状态不可预测8.3 onRestore 中的注意事项版本号必须校验— 确保备份数据与当前应用版本兼容数据迁移必须幂等— 多次恢复同一个备份结果应该一致恢复失败要回滚— 如果恢复过程中出现错误应该回滚到初始状态用户数据优先— 恢复时不要覆盖用户当前已有的新数据总结本文从xiaoshiji_ohos_app项目的EntryBackupAbility.ets出发深入解析了 HarmonyOSBackupExtensionAbility的注册机制、生命周期回调、备份配置文件和版本管理策略。核心要点如下注册机制在module.json5中通过extensionAbilities注册type为backup通过metadata引用backup_config.json配置文件备份配置通过backup_config.json的includes/excludes声明式指定备份范围系统自动处理文件加密和传输onBackup系统在充电Wi-Fi空闲时自动触发开发者可在此执行数据校验和缓存清理onRestore接收BundleVersion参数需要实现版本兼容性处理数据迁移/降级版本管理versionCode编码规范MAJOR1000000 MINOR10000 PATCH*100 BUILD确保版本号能精确比较下一篇文章将深入解析应用包结构HAP/HSP/HAR 的三层架构与 deliveryWithInstall 策略。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源小事记项目源码xiaoshiji_ohos_app官方文档 - 应用模型application-models.md官方文档 - 包结构application-package-structure-stage.md官方文档 - 包开发application-package-dev.md官方文档 - 包基础application-package-fundamentals.md官方文档 - 安装卸载application-package-install-uninstall.md官方文档 - 配置文件application-configuration-file-stage.md开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net