|
|
先说结论:
- 该问题目前只在 OPPO / vivo 的较老系统版本上收到反馈,从反馈来看主要集中在 Android 7.1。
- 严格来说,这不是 MT 主动删除相册文件,而是部分国内厂商对 Android 媒体库逻辑进行定制后出现漏洞,行为与 AOSP 不一致导致的异常。
- 该问题已在 v2.26.7 Patch 1 版本中修复,并已通过 MT 内置更新推送。
MT 是怎么触发这个问题的?
这个问题和系统图库的更新机制有关。
在手机上新增、删除、移动图片文件后,系统图库通常不会立刻感知到这些变化,需要应用通过 MediaScannerConnection 主动通知系统更新媒体库。这样当你打开相册时,才能看到最新的文件变化。
原本无论是新增还是删除文件,直接通过 MediaScannerConnection 把路径发送给系统即可。系统会自动判断这个文件是否存在:文件存在就更新记录,文件不存在就移除图库记录。
但从 Android 10 开始,这种方式变得不太可靠。实际使用中容易出现文件已经删除,但相册里仍然残留显示的问题。
因此在上一个版本中,我换了一种方式:使用 MediaStore 来操作图库记录。相比 MediaScannerConnection,MediaStore 提供了更精确的接口,可以明确控制是新增图片记录,还是删除图片记录。
不过这里有一个潜在风险:MediaStore 的删除操作默认不只是删除图库记录,也会尝试删除记录对应的真实图片文件。
也就是说,理论上会存在这样一种风险:
在 MT 删除文件和 MediaStore 删除图库记录之间的极短时间内,如果同一路径的文件又被重新创建,那么这个新文件可能会被 MediaStore 误删。
针对这个风险,我做了两层防护:
- 使用 MediaStore 的隐藏参数 deletedata=false,强制要求 MediaStore 只删除图库记录,不删除真实文件。这个参数在 AOSP Android 5.0 到 17 中都有对应支持。
- 考虑到手机厂商可能会修改系统实现,即使 deletedata=false 不生效,MT 在真正调用 MediaStore 删除记录之前,也会再次确认本地图片文件已经不存在。
但这次问题就在于:我预估到了厂商系统可能会对 deletedata=false 支持不完整,却没想到部分旧系统的行为偏离得这么严重。
MT 调用删除图库记录的代码大致是这样的:
- contentResolver.delete(rootUri, spec.selection, spec.args)
复制代码
其中 rootUri 是 MediaStore 的 Uri,后面两个参数用于明确告诉系统:我要删除的是哪一个文件对应的图库记录。
但在出现问题的系统上,它不仅忽略了 deletedata=false 这个隐藏参数,甚至连“我要删除哪个文件记录”的筛选条件也疑似被忽略了,最终变成了近似无条件删除图库记录,从而导致大量相册图片被清理。
从用户反馈的弹窗来看,厂商当初修改这块逻辑的目的应该是为了检测是否有恶意 App 通过 MediaStore 大量删除图片。如果检测到,就弹出风险提示:

这个初衷应该是为了保护用户数据,防止恶意删除。但 AOSP 原版 MediaStore 并不存在这个问题,部分厂商修改后的实现反而引入了漏洞,最终成了触发问题的原因。
目前处理方式
v2.26.7 Patch 1 已经回避了这条高风险路径,不再通过 MediaStore 删除图库记录,而是改回通过 MediaScannerConnection 通知系统媒体扫描器同步图库变化。
这样做的主要目的是避免部分厂商系统对 MediaStore 删除接口进行魔改后带来的不可控风险,优先保证不会再触发误删真实图片的问题。
不过这个方案也有取舍:在较新的 Android 系统上,删除文件后的图库更新可能会重新变得不够及时,可能会出现图片文件已经删除,但相册里仍在一段时间内残留显示的情况。这个问题后续我会继续寻找更稳妥的兼容方案。 |
|