用户问:"应用卸载的时候,镜像到系统日历的数据,也同步删除了吗?需要删除,既然卸载就卸载干净。"
当前行为:不会删除。 卸载后系统日历里会留下全部镜像账户(实测 15 个, 名为「同步日历·家庭生活」等),里面是镜像过去的日程,且仍会继续提醒。 用户重装后因为 accId 是新的,这些旧账户被判为孤儿, 但要等重新配好账号并同步一轮才会被清掉;在此之前一直占着位置。
accId
EntryAbility.onDestroy() 不是卸载回调。 SDK 原文 (@ohos.app.ability.UIAbility.d.ts:437-442):
EntryAbility.onDestroy()
@ohos.app.ability.UIAbility.d.ts:437-442
The callback is invoked only when the UIAbility exits gracefully. It is not invoked in cases of abnormal exits…
卸载时进程被系统直接杀掉,走不到这里;即便走到,异步的 deleteCalendar 也来不及完成。
deleteCalendar
网传的卸载钩子全是假的。 在本机 SDK(command-line-tools 26.0.0.851 / API 26) 全文检索:
uninstallDataPolicy
preUninstallHook
preserveCloudData
secureWipeLevel
onBundleRemoved
@ohos.enterprise.EnterpriseAdminExtensionAbility
系统日历数据属于「沙箱外」。 多来源一致: 沙箱内数据卸载自动清除,沙箱外需主动清理。 CalendarManager.createCalendar() 写入的是系统日历数据库,不是应用沙箱。
CalendarManager.createCalendar()
API 不暴露归属,也不提供清理时机。 CalendarAccount 只有 name / type / displayName 三个字段,Calendar 只暴露 readonly id: number。 没有任何包名/owner 字段可声明,也没有「卸载前」回调可挂。
CalendarAccount
name
type
displayName
Calendar
readonly id: number
⇒ 『卸载瞬间自动清干净』在技术上做不到。 只能提供显式清理入口 + 状态兜底。
① 设置页加「一键清除全部镜像」入口(显式、醒目、二次确认)
SystemCalendarMirror.removeAll()
② 强化启动时的孤儿清理
purgeOrphanAccountMirrors()
knownIds
isOurMirrorAccount
knownIds.size === 0
synccalendar.mirror.
build-sc.sh hap
已随 0.2.0 完成并真机验证通过,关闭。
SettingsPage.ets:1305 新增按钮「彻底清除系统日历镜像数据」(wipeAllRunning 状态管理), 二次确认后调用 SystemCalendarMirror.removeAll()。
SettingsPage.ets:1305
wipeAllRunning
关键设计(代码注释里已写明原因):
SystemCalendarMirror.purgeOrphanAccountMirrors()(第 808 行起):
SystemCalendarMirror.purgeOrphanAccountMirrors()
原缺陷(工单已指出):isOurMirrorAccount 里 knownIds.size === 0 一律 return false, 重装后账号库为空 → 孤儿清理完全不动手 → 这正是"重装后残留一直在"的原因。
现修复:引入 AccountStore.isEmptyVaultConfirmed(context) 区分两种情况 ——
AccountStore.isEmptyVaultConfirmed(context)
这个区分是安全关键:knownIds.size === 0 无法分辨"没账号"和"读失败", 贸然全清会误删正常用户的镜像。
工单正文里查证的四点(onDestroy 非卸载回调、网传钩子在本机 SDK 均不存在、 系统日历属沙箱外、CalendarAccount 不暴露归属)—— 结论「卸载瞬间自动清干净 技术上做不到」已写入工单,后续不会有人重复踩。
No dependencies set.
The note is not visible to the blocked user.
现象 / 诉求
用户问:"应用卸载的时候,镜像到系统日历的数据,也同步删除了吗?需要删除,既然卸载就卸载干净。"
当前行为:不会删除。 卸载后系统日历里会留下全部镜像账户(实测 15 个,
名为「同步日历·家庭生活」等),里面是镜像过去的日程,且仍会继续提醒。
用户重装后因为
accId是新的,这些旧账户被判为孤儿,但要等重新配好账号并同步一轮才会被清掉;在此之前一直占着位置。
查证结论(决定性证据)
EntryAbility.onDestroy()不是卸载回调。 SDK 原文(
@ohos.app.ability.UIAbility.d.ts:437-442):卸载时进程被系统直接杀掉,走不到这里;即便走到,异步的
deleteCalendar也来不及完成。网传的卸载钩子全是假的。 在本机 SDK(command-line-tools 26.0.0.851 / API 26)
全文检索:
uninstallDataPolicypreUninstallHookpreserveCloudData/secureWipeLevelonBundleRemoved@ohos.enterprise.EnterpriseAdminExtensionAbility系统日历数据属于「沙箱外」。 多来源一致:
沙箱内数据卸载自动清除,沙箱外需主动清理。
CalendarManager.createCalendar()写入的是系统日历数据库,不是应用沙箱。API 不暴露归属,也不提供清理时机。
CalendarAccount只有name/type/displayName三个字段,Calendar只暴露readonly id: number。没有任何包名/owner 字段可声明,也没有「卸载前」回调可挂。
⇒ 『卸载瞬间自动清干净』在技术上做不到。 只能提供显式清理入口 + 状态兜底。
方案(用户已确认)
① 设置页加「一键清除全部镜像」入口(显式、醒目、二次确认)
SystemCalendarMirror.removeAll())② 强化启动时的孤儿清理
purgeOrphanAccountMirrors()依赖knownIds非空才动手(
isOurMirrorAccount里knownIds.size === 0一律返回 false,安全阀)knownIds为空 → 孤儿清理完全不动手 ⇒ 这正是"重装后残留一直在"的原因仍能清掉带
synccalendar.mirror.前缀的账户 —— 注意与安全阀区分:读不到账号(异常)≠ 账号确实为空
验收标准
build-sc.sh hapBUILD SUCCESSFUL)已随 0.2.0 完成并真机验证通过,关闭。
方案落地情况(对照工单验收标准)
① 设置页「一键清除全部镜像」✅
SettingsPage.ets:1305新增按钮「彻底清除系统日历镜像数据」(wipeAllRunning状态管理),二次确认后调用
SystemCalendarMirror.removeAll()。关键设计(代码注释里已写明原因):
卸载时不会自动清理 ⇒ 只能提供显式入口
② 启动时孤儿清理强化 ✅
SystemCalendarMirror.purgeOrphanAccountMirrors()(第 808 行起):原缺陷(工单已指出):
isOurMirrorAccount里knownIds.size === 0一律 return false,重装后账号库为空 → 孤儿清理完全不动手 → 这正是"重装后残留一直在"的原因。
现修复:引入
AccountStore.isEmptyVaultConfirmed(context)区分两种情况 ——synccalendar.mirror.前缀全清这个区分是安全关键:
knownIds.size === 0无法分辨"没账号"和"读失败",贸然全清会误删正常用户的镜像。
③ 技术结论已记录
工单正文里查证的四点(onDestroy 非卸载回调、网传钩子在本机 SDK 均不存在、
系统日历属沙箱外、CalendarAccount 不暴露归属)—— 结论「卸载瞬间自动清干净
技术上做不到」已写入工单,后续不会有人重复踩。
验收对照