
应用备份恢复与数据安全一、引言用户换机、重装系统后最痛的不是重新下载应用而是看过一半的收藏和设置全没了。HarmonyOS 为应用提供了系统级备份恢复能力通过声明BackupExtensionAbility与backup_config.json应用的数据目录可在云备份、换机迁移等场景下被系统安全地打包、传输与还原。multi-short-video 的四个产品模块都实现了备份能力本文以真实代码为样本拆解备份扩展能力的声明、实现与数据安全设计并给出哪些数据该备份、哪些绝不能备份的边界判定方法。二、备份机制与配置声明HarmonyOS 备份恢复由系统服务驱动系统在备份时机换机、云备份、恢复出厂等唤醒应用注册的备份扩展能力应用回调onBackup将数据交给系统归档恢复时回调onRestore将数据重新写入。应用侧只需做两件事声明扩展能力、提供备份配置。系统负责数据打包、加密传输、跨设备搬运这些重活应用本身不需要感知备份的完整链路。先看配置声明。本工程每个产品模块都在module.json5中注册了一个 type 为 backup 的 ExtensionAbility并关联备份配置文件// products/default/src/main/module.json5pc/tv/wearable 模块结构相同 extensionAbilities: [ { name: MultiShortVideoDefaultBackupAbility, srcEntry: ./ets/defaultbackupability/MultiShortVideoDefaultBackupAbility.ets, type: backup, exported: false, metadata: [ { name: ohos.extension.backup, resource: $profile:backup_config } ] } ]关键点type必须是backupexported为 false因为备份扩展只被系统服务调用不应暴露给其他应用拉起metadata中name固定为ohos.extension.backupresource指向resources/base/profile/backup_config.json。该配置文件内容极简// products/default/src/main/resources/base/profile/backup_config.json { allowToBackupRestore: true }allowToBackupRestore是总开关置 true 表示应用允许被系统备份与恢复。该文件还支持更细粒度的控制字段fullBackupOnly限定仅参与整机备份excludes排除指定目录includes指定参与备份的目录。字段优先级与继承规则在不同版本略有差异官方文档是最终依据实践时建议先全量、后收紧第一版只开总开关跑通链路再逐步用 excludes 把缓存与日志排除掉。三、备份扩展能力的实现四个产品模块的备份 Ability 实现完全一致以 default 模块为例// products/default/src/main/ets/defaultbackupability/MultiShortVideoDefaultBackupAbility.ets import { hilog } from kit.PerformanceAnalysisKit; import { BackupExtensionAbility, BundleVersion } from kit.CoreFileKit; const DOMAIN 0x0000; export default class DefaultBackupAbility 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(); } }类继承自kit.CoreFileKit的BackupExtensionAbility实现两个钩子onBackup()系统准备备份应用数据时回调。若应用有需要预处理的逻辑如把内存态状态刷入 Preferences、关闭正在写的文件、停止后台任务在此执行无特殊逻辑时保持空实现即可系统会自动归档沙箱内数据。onRestore(bundleVersion)恢复完成后回调参数携带备份来源的版本信息。可据此做数据迁移例如备份来自 1.0.0当前是 1.1.0则在此处执行一次版本化迁移保证老数据结构能平滑升级。日志中%{public}s为隐私占位符%{public}s会脱敏打印、%{s}明文打印这里使用%{public}s避免把 bundle 内部细节泄露到系统日志。其余三个产品的实现MultiShortVideoPcBackupAbility.ets、MultiShortVideoTvBackupAbility.ets、MultiShortVideoWearableBackupAbility.ets除类名外完全同构位于各自产品的pcbackupability、tvbackupability、wearablebackupability目录下体现了四个入口、同一备份策略的设计——备份逻辑与 UI 无关四端复用同一套能力实现只是各挂一个入口类。使用备份扩展还要注意三个生命周期约束。其一备份扩展是后台扩展没有 UI 上下文不能在 onBackup/onRestore 中弹窗或跳页面任何需要用户确认的动作都应提前在前台完成。其二回调有超时约束系统不会无限等待onBackup/onRestore 中的耗时操作如网络上传、大规模文件整理应在回调外异步完成回调内只做必要的落盘与状态收尾本工程的空实现加await Promise.resolve()正是这种轻回调的示范。其三备份期间应用可能被系统冻结不要依赖备份回调内的定时器或监听器回调应当是一次性、幂等的——即使被调用两次也不能产生重复数据或脏数据。四、备份范围与数据安全设计备份并非全盘拷贝系统只会归档应用沙箱内允许访问的目录data/app/el2/100/base/包名 下的 files、preferences 等数据库、缓存目录等默认可被备份。开发者应主动划定备份边界数据是否应备份说明用户设置Preferences 首选项是播放位置、页签索引、主题偏好收藏/点赞本地缓存是换机后用户体验连续视频缓存文件否体积大、可从网络重建账号 Token/密钥否高敏数据应走账号同步而非本地备份日志、临时文件否无价值且增大备份体积对不应备份的目录可在backup_config.json中用excludes排除。数据安全上要遵循三条红线权限最小化本工程仅声明一个受限权限ohos.permission.DETECT_GESTURE见 default 模块 module.json5 的 requestPermissions备份链路本身不需要任何额外权限——这也是判断备份配置是否合规的简单标准备份不应该成为申请权限的理由。敏感数据不落盘账号凭据应存于系统账密管理能力kit.BasicServicesKit的 Asset Store而不是 Preferences——后者会被备份机制打包扩大泄露面。Asset Store 中的数据独立加密存储系统备份时也不会随普通数据目录搬运。日志脱敏onRestore 打印版本信息使用%{public}s而非%{s}避免把 bundle 内部数据带入系统日志业务侧打印用户相关数据时也应统一脱敏。备份包的加密由系统负责开发者不需要也不应该自行加密整个数据目录——过度自研加密反而会破坏备份的可恢复性。正确的做法是分级安全普通偏好数据裸存、可备份敏感凭据进 Asset Store、不备份。五、卸载重装与账号数据隔离备份恢复与卸载重装是两条不同的数据通路备份恢复换机/云备份场景系统级搬运整个数据目录应用无感用户无需登录即可找回本地数据。卸载重装默认清空沙箱数据本工程module.json5中deliveryWithInstall: false表示应用随设备预置或单独安装installationFree: false表示不支持免安装运行——免安装场景下沙箱数据不保留必须依赖备份或账号云端同步。因此推荐的数据架构是三层分离设备本地数据播放位置、界面偏好走备份恢复用户资产数据收藏、作品走账号同步到服务端不可再生数据视频缓存不备份也不入账号。对多设备应用而言同一账号在手机与平板的观看进度理论上应通过云端账号体系对齐本地备份只负责兜底单设备的连续性——本工程用内存 mock 数据演示交互工程化落地时应把WorksDataModel、CommentDataModel这类模型与账号服务绑定而不是塞进本地备份包。原因有二一是账号资产跨端共享天然应由云端承载本地备份无法解决另一台设备的同步二是备份包一旦包含用户内容就升级为个人信息处理场景隐私合规成本陡增。六、备份恢复的验证与排障备份能力接入后必须实测不能只看配置。验证路径分两步安装后验证注册安装应用后查看系统日志或使用hdc shell bm dump --extension-type backup确认备份扩展已被系统识别若看不到对应 Ability说明 module.json5 的 metadata 声明或 backup_config.json 路径有误。触发真实备份/恢复通过系统云备份或换机助手触发一次备份卸载重装或在新设备安装后执行恢复验证onBackup与onRestore日志按预期打印、Preferences 中的播放位置与页签索引确实还原。恢复后首次启动建议在onRestore中打印bundleVersion人工核对来源版本与迁移分支是否命中。排障时最常遇到的三类问题现象可能原因处置备份扩展未被调用metadata 的 resource 指向错误检查$profile:backup_config与文件是否同名恢复后数据缺失数据位于 excludes 排除目录核对 backup_config 的排除规则恢复后崩溃备份版本数据结构与当前版本不兼容在 onRestore 中按 BundleVersion 做迁移这三个问题的共同点是把备份当成一次性配置缺少版本视角数据结构一旦演进就必须同步维护恢复侧的迁移逻辑否则备份反而成为升级的隐患。七、总结与最佳实践备份恢复是把换机零丢失变成产品卖点的系统能力成本极低但收益明显。本工程四个产品模块通过一个 backup 扩展 一个配置开关即完成了能力接入值得所有应用参考。最佳实践归纳为显式声明在 module.json5 注册type: backup扩展并在 metadata 中关联$profile:backup_configallowToBackupRestore置 true。默认空实现无预处理逻辑时 onBackup/onRestore 保持空实现系统自动完成归档不要在里面做耗时业务备份回调有超时约束。版本化迁移利用 onRestore 的BundleVersion参数做数据结构迁移兼容老版本备份包升级数据模型时同步维护迁移逻辑。划清备份边界用 excludes 排除缓存与日志Token 等敏感数据走 Asset/账号体系绝不进入备份包。卸载策略区分明确备份恢复与卸载重装两条通路账号数据与本地数据严格隔离避免把云端资产误入本地备份引发隐私风险。备份能力接入很简单但备份什么、不备份什么才是真正的设计题。把数据分级模型想清楚备份恢复就能成为多设备体验的加分项而不是隐私合规的隐患。