通过SAF获取Tree URI后,注册ContentObserver无法监听文件变更
问题:SAF获取的Tree URI无法用ContentObserver监听文件变更
我通过Storage Access Framework的ACTION_OPEN_DOCUMENT_TREE拿到了用户所选文件夹的读写权限,得到对应的Tree URI,但ContentObserver完全监听不到该目录及其子目录的文件变更——不管是创建、编辑、重命名还是删除文本文件,下面代码里的onChange()方法一次都没触发过。
测试代码
val contentObserver = object : ContentObserver(null) { override fun onChange(selfChange: Boolean) { Log.v("myapp", "change detected") } override fun onChange(selfChange: Boolean, uri: Uri?) { Log.v("myapp", "change detected") } } requireActivity().contentResolver.registerContentObserver(tree_uri, true, contentObserver)
原因与解决方案
在API Level 29及以上,Android系统限制了ContentObserver对SAF Tree URI的监听能力,这是系统层面的设计限制,无法直接通过原有代码解决。可以尝试以下替代方案:
- 定期轮询目录:用
WorkManager或定时任务,通过DocumentFile.fromTreeUri()获取目录下的文件列表,定期对比差异来检测变更。这种方式兼容性好,但会有一定的延迟。 - 针对媒体文件用MediaStore监听:如果监听的是媒体文件目录(比如相册、视频文件夹),可以注册
MediaStore对应媒体类型的URI的ContentObserver,但非媒体文件不适用。 - 全局存储变更监听+过滤:注册
MediaStore.Files.getContentUri("external")的ContentObserver,在回调里判断变更的文件是否属于你通过SAF获取的目录范围。这种方式会收到大量无关通知,需要额外做路径匹配过滤。
内容的提问来源于stack exchange,提问作者dmc7z
相关产品推荐
相关产品推荐

