UnoPlatform开发Android应用访问外接U盘时ListFiles返回null问题求助
问题根因定位
- 你当前通过
Context.GetExternalFilesDirs("")拿到的路径,根本不是U盘的根目录,是系统为你的应用在U盘存储上分配的专属私有目录,也就是/storage/[U盘卷标]/Android/data/[你的包名]/files。这类目录不需要额外权限就能读写,但默认是空的,仅用来存放你应用自己生成的文件,和U盘上用户实际存放的公共文件区是完全隔离的,根本遍历不到用户的文件结构。 - 现在
ListFiles()返回null的直接原因:在Android 11及以上版本,哪怕你配置了android:requestLegacyExternalStorage="true",系统对可移动存储上的空专属目录做了特殊处理,部分厂商定制ROM会直接在目录为空的时候返回null而不是空文件数组,这不是你权限没给够导致的。 - 如果你想遍历整个U盘的文件结构,光靠
READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE这类权限是完全没用的——从Android 10开始,普通应用就不允许直接通过路径遍历的方式访问可移动存储的根目录,就算所有权限都授满也不行。
落地解决步骤
- 先修正专属目录的返回值兼容逻辑,把空目录场景的null做兜底处理,不要把null当成异常:
// 空目录下ListFiles可能返回null,直接兜底为空集合避免空引用 var directoryEntries = extDir?.ListFiles() ?? Array.Empty<Java.IO.File>(); - 如果你的核心需求是读取U盘上用户存放的实际文件结构,放弃直接硬拼路径遍历的思路,改用系统自带的存储访问框架(SAF)完成授权:
- 发起
Intent.ActionOpenDocumentTree跳转系统授权页,让用户手动选中U盘的根目录完成授权,授权拿到的文档树URI可以持久化保存,后续不需要重复弹窗。 - 拿到授权后,完全不需要申请任何外部存储权限,就能遍历该授权目录下的所有子文件夹和文件。Uno Platform本身已经对SAF做了跨平台适配,不需要写额外的原生交互代码。
- 发起
- 清理无效的Manifest配置:
android:requestLegacyExternalStorage="true"在Android 11以上对可移动存储完全失效,甚至可能导致SAF授权异常,针对新版本目标API的应用可以直接删掉这段配置。- 针对Android 13以上版本,老的全量外部存储权限已经被拆分,按需申请细分媒体权限即可,全量的读写权限申请在新版本系统上没有任何实际效果。
高频踩坑提醒
- 不要尝试直接硬拼U盘根目录路径(比如
/storage/5CD7-B286/)来执行ListFiles(),Android 11以上系统会在沙箱层面直接拦截访问,就算CanRead()返回true也拿不到任何内容,不是代码逻辑写错的问题。 - 不要把“拿到应用专属目录的访问权”等同于“拿到了U盘全部目录的访问权”,这两者是完全独立的沙箱分区,没有任何遍历关联。
内容的提问来源于stack exchange,提问作者Emanuele Leoni
相关产品推荐
相关产品推荐

