Android 11 SAF场景下调用native fdopendir+readdir仅显示媒体文件如何获取全文件列表
问题原因
Android 11强制启用了分区存储(Scoped Storage)机制,系统对SAF返回的目录文件描述符做了底层过滤,原生层通过readdir读取该类目录fd时,仅会返回图片、音频、视频三类媒体文件,非媒体类文件会被系统隐藏。该机制属于系统层级的限制,因此Android 10及更早版本可用的逻辑在Android 11上失效。
合规解决方案
最符合谷歌权限设计规范的实现方式是将目录遍历逻辑从原生层迁移到Java/Kotlin层,使用SAF官方提供的API遍历目录,具体步骤如下:
- 用
DocumentFile.fromTreeUri(context, uri)获取你授权目录对应的DocumentFile实例 - 调用该实例的
listFiles()方法,即可获取目录下所有类型的文件、子目录列表,不会被系统过滤 - 如果原生层需要操作单个文件,可以单独获取目标文件的fd传给原生层读写,不要把目录fd传给原生层做遍历操作
其他可选方案
如果确实需要保留原生层遍历目录的逻辑,可以选择以下两种方案,但均有适用限制:
- 申请
MANAGE_EXTERNAL_STORAGE特殊权限,获取外部存储完整访问权限后,目录fd遍历将不受过滤限制。但该权限仅允许文件管理、安全杀毒等特定类型的应用上架谷歌Play商店,普通应用申请会被驳回 - 临时将
targetSdkVersion降到29(Android 10),同时在Manifest中配置android:requestLegacyExternalStorage="true",该配置在Android 11设备上仍然生效,可暂时规避过滤限制,但Android 12及以上版本会忽略该配置,仅可作为过渡方案
内容的提问来源于stack exchange,提问作者user1063364
相关产品推荐
相关产品推荐

